diff --git a/MatterControl.MeshOperations/OperationSourceContainerObject3D.cs b/MatterControl.MeshOperations/OperationSourceContainerObject3D.cs index 14783a8d5..02647ad44 100644 --- a/MatterControl.MeshOperations/OperationSourceContainerObject3D.cs +++ b/MatterControl.MeshOperations/OperationSourceContainerObject3D.cs @@ -192,8 +192,8 @@ namespace MatterHackers.MatterControl.DesignTools.Operations { await Rebuild(); } - else if (invalidateType.InvalidateType.HasFlag(InvalidateType.Properties) - && invalidateType.Source == this) + else if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Properties) && invalidateType.Source == this) + || invalidateType.InvalidateType.HasFlag(InvalidateType.SheetUpdated)) { await Rebuild(); } diff --git a/MatterControlLib/DesignTools/Operations/ScaleObject3D_3.cs b/MatterControlLib/DesignTools/Operations/ScaleObject3D_3.cs index d782400b3..36857ad1a 100644 --- a/MatterControlLib/DesignTools/Operations/ScaleObject3D_3.cs +++ b/MatterControlLib/DesignTools/Operations/ScaleObject3D_3.cs @@ -133,7 +133,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations [MaxDecimalPlaces(3)] [JsonIgnore] - public DoubleOrExpression Width + public double Width { get { @@ -150,14 +150,14 @@ namespace MatterHackers.MatterControl.DesignTools.Operations var children = UntransformedChildren; if (children != null) { - FixIfLockedProportions(0, value.Value(this) / UntransformedChildren.GetAxisAlignedBoundingBox().XSize); + FixIfLockedProportions(0, value / UntransformedChildren.GetAxisAlignedBoundingBox().XSize); } } } [MaxDecimalPlaces(3)] [JsonIgnore] - public DoubleOrExpression Depth + public double Depth { get { @@ -174,14 +174,14 @@ namespace MatterHackers.MatterControl.DesignTools.Operations var children = UntransformedChildren; if (children != null) { - FixIfLockedProportions(1, value.Value(this) / children.GetAxisAlignedBoundingBox().YSize); + FixIfLockedProportions(1, value / children.GetAxisAlignedBoundingBox().YSize); } } } [MaxDecimalPlaces(3)] [JsonIgnore] - public DoubleOrExpression Height + public double Height { get { @@ -198,7 +198,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations var children = UntransformedChildren; if (children != null) { - FixIfLockedProportions(2, value.Value(this) / children.GetAxisAlignedBoundingBox().ZSize); + FixIfLockedProportions(2, value / children.GetAxisAlignedBoundingBox().ZSize); } } } diff --git a/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs b/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs index f0cd5dc9d..fe0a2fd1a 100644 --- a/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs +++ b/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs @@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using MatterHackers.Agg; @@ -62,31 +63,49 @@ namespace MatterHackers.MatterControl.DesignTools return item; } + public override Mesh Mesh + { + get + { + if (this.Children.Where(i => i.Mesh == null).Any()) + { + this.Children.Modify((list) => + { + list.Clear(); + Mesh border; + using (Stream stlStream = StaticData.Instance.OpenStream(Path.Combine("Stls", "sheet_border.stl"))) + { + border = StlProcessing.Load(stlStream, CancellationToken.None); + } + list.Add(new Object3D() + { + Mesh = border, + Color = new Color("#9D9D9D") + }); + Mesh boxes; + using (Stream stlStream = StaticData.Instance.OpenStream(Path.Combine("Stls", "sheet_boxes.stl"))) + { + boxes = StlProcessing.Load(stlStream, CancellationToken.None); + } + list.Add(new Object3D() + { + Mesh = boxes, + Color = new Color("#117c43") + }); + + var aabb = border.GetAxisAlignedBoundingBox(); + this.Matrix *= Matrix4X4.CreateScale(20 / aabb.XSize); + }); + } + + return null; + } + + set => base.Mesh = value; + } + public SheetObject3D() { - Mesh border; - using (Stream stlStream = StaticData.Instance.OpenStream(Path.Combine("Stls", "sheet_border.stl"))) - { - border = StlProcessing.Load(stlStream, CancellationToken.None); - } - this.Children.Add(new Object3D() - { - Mesh = border, - Color = new Color("#9D9D9D") - }); - Mesh boxes; - using (Stream stlStream = StaticData.Instance.OpenStream(Path.Combine("Stls", "sheet_boxes.stl"))) - { - boxes = StlProcessing.Load(stlStream, CancellationToken.None); - } - this.Children.Add(new Object3D() - { - Mesh = boxes, - Color = new Color("#117c43") - }); - - var aabb = border.GetAxisAlignedBoundingBox(); - this.Matrix *= Matrix4X4.CreateScale(20 / aabb.XSize); } public override bool Persistable => false; @@ -109,51 +128,94 @@ namespace MatterHackers.MatterControl.DesignTools } } + internal class UpdateItem + { + internal int depth; + internal IObject3D item; + internal RebuildLock rebuildLock; + } private void SendInvalidateToAll() { - var updatedItems = new HashSet(); - updatedItems.Add(this); + var updateItems = new List(); foreach (var sibling in this.Parent.Children) { - SendInvalidateRecursive(sibling, updatedItems); - } - } - - private void SendInvalidateRecursive(IObject3D item, HashSet updatedItems) - { - if (updatedItems.Contains(item)) - { - return; + if (sibling != this) + { + AddItemsToList(sibling, updateItems, 0); + } } - // process depth first - foreach(var child in item.Children) + // sort them + updateItems.Sort((a, b) => a.depth.CompareTo(b.depth)); + // lock everything + foreach (var depthItem in updateItems) { - SendInvalidateRecursive(child, updatedItems); + depthItem.rebuildLock = depthItem.item.RebuildLock(); } // and send the invalidate RunningInterval runningInterval = null; void RebuildWhenUnlocked() { - if (!item.RebuildLocked) + // get the last item from the list + var index = updateItems.Count - 1; + var updateItem = updateItems[index]; + // if it is locked from above + if (updateItem.rebuildLock != null) + { + // release the lock and rebuild + // and ask it to update + var depthToBuild = updateItem.depth; + for (int i = 0; i < updateItems.Count; i++) + { + if (updateItems[i].depth == updateItem.depth) + { + updateItems[i].rebuildLock.Dispose(); + updateItems[i].rebuildLock = null; + updateItems[i].item.Invalidate(new InvalidateArgs(updateItems[i].item, InvalidateType.SheetUpdated)); + } + } + } + else if (updateItems.Where(i => i.depth == updateItem.depth && i.item.RebuildLocked).Any()) + { + // wait for the current rebuild to end + return; + } + else + { + // remove all items at this level + for (int i = updateItems.Count - 1; i >= 0; i--) + { + if (updateItems[i].depth == updateItem.depth) + { + updateItems.RemoveAt(i); + } + } + } + + if (updateItems.Count == 0) { - updatedItems.Add(item); UiThread.ClearInterval(runningInterval); - item.Invalidate(new InvalidateArgs(item, InvalidateType.SheetUpdated)); } } - if (!item.RebuildLocked) + // rebuild depth first + runningInterval = UiThread.SetInterval(RebuildWhenUnlocked, .01); + } + + private void AddItemsToList(IObject3D inItem, List updatedItems, int inDepth) + { + // process depth first + foreach(var child in inItem.Children) { - updatedItems.Add(item); - item.Invalidate(new InvalidateArgs(item, InvalidateType.SheetUpdated)); + AddItemsToList(child, updatedItems, inDepth + 1); } - else + + updatedItems.Add(new UpdateItem() { - // we need to get back to the user requested change when not locked - runningInterval = UiThread.SetInterval(RebuildWhenUnlocked, .2); - } + depth = inDepth, + item = inItem + }); } public static T EvaluateExpression(IObject3D owner, string inputExpression) diff --git a/MatterControlLib/PartPreviewWindow/MainViewWidget.cs b/MatterControlLib/PartPreviewWindow/MainViewWidget.cs index 9209610a7..ded0153d7 100644 --- a/MatterControlLib/PartPreviewWindow/MainViewWidget.cs +++ b/MatterControlLib/PartPreviewWindow/MainViewWidget.cs @@ -398,7 +398,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow statusMessage = tasksContainer.AddChild(new TextWidget("") { - Margin = new BorderDouble(5, 0, 0, 0), + Margin = new BorderDouble(5, 0, 0, 3), TextColor = theme.TextColor, VAnchor = VAnchor.Center, PointSize = theme.FontSize9, diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs index f940a2b78..26716a23b 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/CombineObject3D_2.cs @@ -36,7 +36,6 @@ using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.DesignTools.Operations; -using MatterHackers.PolygonMesh; using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs index 1ac5f10b5..66d5c6193 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/SubtractObject3D_2.cs @@ -105,8 +105,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { await Rebuild(); } - else if (invalidateType.InvalidateType.HasFlag(InvalidateType.Properties) - && invalidateType.Source == this) + else if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Properties) && invalidateType.Source == this) + || invalidateType.InvalidateType.HasFlag(InvalidateType.SheetUpdated)) { await Rebuild(); } diff --git a/MatterControlLib/PartPreviewWindow/View3D/SceneActions.cs b/MatterControlLib/PartPreviewWindow/View3D/SceneActions.cs index fb267d224..d06da859c 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/SceneActions.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/SceneActions.cs @@ -144,7 +144,16 @@ namespace MatterHackers.MatterControl.PartPreviewWindow // Clear selection to ensure all root level children are arranged on the bed scene.SelectedItem = null; - var children = scene.Children.ToList().Where(item => item.Persistable == true).ToList(); + var children = scene.Children.ToList().Where(item => + { + var aabb = item.WorldAxisAlignedBoundingBox(); + if (aabb.Center.Length > 1000) + { + return true; + } + + return item.Persistable == true; + }).ToList(); var transformData = new List(); foreach (var child in children) { diff --git a/StaticData/Images/Thumbnails/15629556794206744455-256x256.png b/StaticData/Images/Thumbnails/15629556794206744455-256x256.png index 15563986b..84487ac0b 100644 Binary files a/StaticData/Images/Thumbnails/15629556794206744455-256x256.png and b/StaticData/Images/Thumbnails/15629556794206744455-256x256.png differ diff --git a/StaticData/Images/Thumbnails/15936583715112407855-256x256.png b/StaticData/Images/Thumbnails/15936583715112407855-256x256.png new file mode 100644 index 000000000..0eea0fdf4 Binary files /dev/null and b/StaticData/Images/Thumbnails/15936583715112407855-256x256.png differ diff --git a/StaticData/Images/Thumbnails/16091828042932597356-256x256.png b/StaticData/Images/Thumbnails/16091828042932597356-256x256.png new file mode 100644 index 000000000..1a3075fe0 Binary files /dev/null and b/StaticData/Images/Thumbnails/16091828042932597356-256x256.png differ diff --git a/StaticData/Images/Thumbnails/16441270457604260047-256x256.png b/StaticData/Images/Thumbnails/16441270457604260047-256x256.png index 60de98736..f820ef35c 100644 Binary files a/StaticData/Images/Thumbnails/16441270457604260047-256x256.png and b/StaticData/Images/Thumbnails/16441270457604260047-256x256.png differ diff --git a/StaticData/Images/Thumbnails/16528515837811985426-256x256.png b/StaticData/Images/Thumbnails/16528515837811985426-256x256.png index f17e79968..f75ae5e28 100644 Binary files a/StaticData/Images/Thumbnails/16528515837811985426-256x256.png and b/StaticData/Images/Thumbnails/16528515837811985426-256x256.png differ diff --git a/StaticData/Images/Thumbnails/17249460686226192632-256x256.png b/StaticData/Images/Thumbnails/17249460686226192632-256x256.png index 15eec47cb..4fde920ec 100644 Binary files a/StaticData/Images/Thumbnails/17249460686226192632-256x256.png and b/StaticData/Images/Thumbnails/17249460686226192632-256x256.png differ diff --git a/StaticData/Images/Thumbnails/17412128430684605466-256x256.png b/StaticData/Images/Thumbnails/17412128430684605466-256x256.png index 62986b97b..80130b935 100644 Binary files a/StaticData/Images/Thumbnails/17412128430684605466-256x256.png and b/StaticData/Images/Thumbnails/17412128430684605466-256x256.png differ diff --git a/StaticData/Images/Thumbnails/17603298558383392052-256x256.png b/StaticData/Images/Thumbnails/17603298558383392052-256x256.png index 43fde6746..734c3be24 100644 Binary files a/StaticData/Images/Thumbnails/17603298558383392052-256x256.png and b/StaticData/Images/Thumbnails/17603298558383392052-256x256.png differ diff --git a/StaticData/Images/Thumbnails/18166844333149700895-256x256.png b/StaticData/Images/Thumbnails/18166844333149700895-256x256.png index dc5ed25f2..7137508d4 100644 Binary files a/StaticData/Images/Thumbnails/18166844333149700895-256x256.png and b/StaticData/Images/Thumbnails/18166844333149700895-256x256.png differ diff --git a/StaticData/Images/Thumbnails/3979214300947947730-256x256.png b/StaticData/Images/Thumbnails/3979214300947947730-256x256.png index 0b67e737e..dfd8b13be 100644 Binary files a/StaticData/Images/Thumbnails/3979214300947947730-256x256.png and b/StaticData/Images/Thumbnails/3979214300947947730-256x256.png differ diff --git a/StaticData/Images/Thumbnails/5104802733015559249-256x256.png b/StaticData/Images/Thumbnails/5104802733015559249-256x256.png index d9e48eb0e..555ceb08d 100644 Binary files a/StaticData/Images/Thumbnails/5104802733015559249-256x256.png and b/StaticData/Images/Thumbnails/5104802733015559249-256x256.png differ diff --git a/StaticData/Images/Thumbnails/53638108346200266-256x256.png b/StaticData/Images/Thumbnails/53638108346200266-256x256.png index 6d1c0d687..bd24c13e0 100644 Binary files a/StaticData/Images/Thumbnails/53638108346200266-256x256.png and b/StaticData/Images/Thumbnails/53638108346200266-256x256.png differ diff --git a/StaticData/Images/Thumbnails/6528493062500962036-256x256.png b/StaticData/Images/Thumbnails/6528493062500962036-256x256.png index ae5476f3a..e85e216b1 100644 Binary files a/StaticData/Images/Thumbnails/6528493062500962036-256x256.png and b/StaticData/Images/Thumbnails/6528493062500962036-256x256.png differ diff --git a/StaticData/Images/Thumbnails/6544321702223751471-256x256.png b/StaticData/Images/Thumbnails/6544321702223751471-256x256.png index dffe6c2db..f2aacd19d 100644 Binary files a/StaticData/Images/Thumbnails/6544321702223751471-256x256.png and b/StaticData/Images/Thumbnails/6544321702223751471-256x256.png differ diff --git a/StaticData/Images/Thumbnails/7598956486737020828-256x256.png b/StaticData/Images/Thumbnails/7598956486737020828-256x256.png index d3aa03f92..ee11703b9 100644 Binary files a/StaticData/Images/Thumbnails/7598956486737020828-256x256.png and b/StaticData/Images/Thumbnails/7598956486737020828-256x256.png differ diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 78d54a573..4f3afb009 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 78d54a573392075ebc0b7579d245eb17df539a39 +Subproject commit 4f3afb00997203e206eebef6e1dfc5858b0a2fe1 diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 53e703573..0b4c79769 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 53e703573d54be5bf4962483abfbb8c91dff11c4 +Subproject commit 0b4c79769aa23a62df17f10ec771c0bb95cdb352 diff --git a/Tests/MatterControl.AutomationTests/DesignTools/PrimitveTests.cs b/Tests/MatterControl.AutomationTests/DesignTools/PrimitveTests.cs index a1d020721..eaf1563a6 100644 --- a/Tests/MatterControl.AutomationTests/DesignTools/PrimitveTests.cs +++ b/Tests/MatterControl.AutomationTests/DesignTools/PrimitveTests.cs @@ -13,7 +13,7 @@ namespace MatterHackers.MatterControl.Tests.Automation public class PrimitiveAndSheetsTests { [Test] - public async Task DimensionsWorkWithSheets() + public async Task DimensionsWorkWhenNoSheet() { await MatterControlUtilities.RunTest((testRunner) => { @@ -83,5 +83,77 @@ namespace MatterHackers.MatterControl.Tests.Automation return Task.CompletedTask; }, overrideWidth: 1300, maxTimeToRun: 60); } + + [Test] + public async Task ScaleObjectWorksWithAndWithoutSheet() + { + await MatterControlUtilities.RunTest((testRunner) => + { + testRunner.OpenEmptyPartTab(); + + var primitive = "Cube"; + var primitiveName = "Row Item " + primitive; + testRunner.DoubleClickByName(primitiveName); + + // Get View3DWidget + View3DWidget view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget; + var scene = view3D.Object3DControlLayer.Scene; + + testRunner.WaitForName(primitive); + Assert.AreEqual(1, scene.Children.Count, "Should have 1 part"); + + var cube = testRunner.GetObjectByName(primitive, out _) as CubeObject3D; + + Assert.AreEqual(20, cube.Width.Value(cube)); + + // Select scene object + testRunner.Select3DPart(primitive); + + // Scale it wider + testRunner.DragDropByName("ScaleWidthRight", + "ScaleWidthRight", + offsetDrag: new Point2D(0, 0), + offsetDrop: new Point2D(0, 10)); + Assert.Greater(cube.Width.Value(cube), 20.0); + + testRunner.ClickByName("3D View Undo"); + Assert.AreEqual(20, cube.Width.Value(cube)); + + // try scaling by text entry + testRunner.ClickByName("ScaleWidthLeft") + .ClickByName("XValueDisplay") + .Type("35") + .Type("{Enter}"); + + Assert.AreEqual(35, cube.Width.Value(cube)); + + testRunner.ClickByName("3D View Undo"); + Assert.AreEqual(20, cube.Width.Value(cube)); + + // try scaling by text entry of an equation + testRunner.ClickByName("Width Field") + .Type("=40 + 5") + .Type("{Enter}"); + + Assert.AreEqual(45, cube.Width.Value(cube)); + + // Select Nothing + testRunner.ClickByName("View3DWidget"); + testRunner.Type(" "); + Assert.AreEqual(null, scene.SelectedItem); + // and re-select the object + testRunner.Type("^a"); + Assert.AreEqual(1, scene.Children.Count); + Assert.AreEqual(cube, scene.SelectedItem); + + // now that has an equation in the width it should not have an x edge controls + Assert.IsFalse(testRunner.NameExists("ScaleWidthRight", .2)); + + testRunner.ClickByName("3D View Undo"); + Assert.AreEqual(20, cube.Width.Value(cube)); + + return Task.CompletedTask; + }, overrideWidth: 1300, maxTimeToRun: 60); + } } }