From 99ef697d16383135262eb0d52f0877dad20ce541 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Fri, 1 Jun 2018 17:44:46 -0700 Subject: [PATCH] Subtract is working now Added child selector got align updating correctly got array operations working with source object fit to bounds updating correctly took out hole output type improved text object issue: MatterHackers/MCCentral#3456 Second subtract creates bad data --- DesignTools/EditableTypes/DirectionAxis.cs | 39 ++++ DesignTools/EditableTypes/DirectionVector.cs | 38 ++++ DesignTools/Operations/Align3D.cs | 6 +- DesignTools/Operations/ArrayAdvanced3D.cs | 11 -- DesignTools/Operations/ArrayLinear3D.cs | 1 + DesignTools/Operations/ArrayRadial3D.cs | 1 + DesignTools/Operations/FitToBounds3D.cs | 12 +- DesignTools/Primitives/TextObject3D.cs | 42 ++-- DesignTools/PublicPropertyEditor.cs | 126 +++++++++++- MatterControl.csproj | 3 +- .../View3D/Actions/CombineEditor.cs | 10 +- .../View3D/Actions/IntersectionEditor.cs | 14 +- .../View3D/Actions/SubtractAndReplace.cs | 26 +-- .../View3D/Actions/SubtractEditor.cs | 179 ------------------ .../View3D/Actions/SubtractObject3D.cs | 115 +++++------ PartPreviewWindow/View3D/MeshViewerWidget.cs | 4 - Submodules/MatterSlice | 2 +- Submodules/agg-sharp | 2 +- Tests/MatterControl.Tests/SceneTests.cs | 4 +- 19 files changed, 311 insertions(+), 324 deletions(-) create mode 100644 DesignTools/EditableTypes/DirectionAxis.cs create mode 100644 DesignTools/EditableTypes/DirectionVector.cs delete mode 100644 PartPreviewWindow/View3D/Actions/SubtractEditor.cs diff --git a/DesignTools/EditableTypes/DirectionAxis.cs b/DesignTools/EditableTypes/DirectionAxis.cs new file mode 100644 index 000000000..2b1f436b0 --- /dev/null +++ b/DesignTools/EditableTypes/DirectionAxis.cs @@ -0,0 +1,39 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools.EditableTypes +{ + public class DirectionAxis + { + public Vector3 Normal { get; set; } + public Vector3 Origin { get; set; } + } +} \ No newline at end of file diff --git a/DesignTools/EditableTypes/DirectionVector.cs b/DesignTools/EditableTypes/DirectionVector.cs new file mode 100644 index 000000000..3dbc7a7b1 --- /dev/null +++ b/DesignTools/EditableTypes/DirectionVector.cs @@ -0,0 +1,38 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools.EditableTypes +{ + public class DirectionVector + { + public Vector3 Normal { get; set; } + } +} \ No newline at end of file diff --git a/DesignTools/Operations/Align3D.cs b/DesignTools/Operations/Align3D.cs index 39f7b88f9..a54988f62 100644 --- a/DesignTools/Operations/Align3D.cs +++ b/DesignTools/Operations/Align3D.cs @@ -444,12 +444,13 @@ namespace MatterHackers.MatterControl.DesignTools.Operations }); ResumeRebuild(); - Invalidate(new InvalidateArgs(this, InvalidateType.Matrix)); } public override void Remove(UndoBuffer undoBuffer) { + SuspendRebuild(); + // put everything back to where it was before the arrange started if (OriginalChildrenBounds.Count == Children.Count) { @@ -463,6 +464,9 @@ namespace MatterHackers.MatterControl.DesignTools.Operations } base.Remove(undoBuffer); + + ResumeRebuild(); + Invalidate(new InvalidateArgs(this, InvalidateType.Content)); } public void UpdateControls(PPEContext context) diff --git a/DesignTools/Operations/ArrayAdvanced3D.cs b/DesignTools/Operations/ArrayAdvanced3D.cs index 7d0de74e1..6b154ed3a 100644 --- a/DesignTools/Operations/ArrayAdvanced3D.cs +++ b/DesignTools/Operations/ArrayAdvanced3D.cs @@ -104,15 +104,4 @@ namespace MatterHackers.MatterControl.DesignTools.Operations base.Remove(undoBuffer); } } - - public class DirectionAxis - { - public Vector3 Normal { get; set; } - public Vector3 Origin { get; set; } - } - - public class DirectionVector - { - public Vector3 Normal { get; set; } - } } \ No newline at end of file diff --git a/DesignTools/Operations/ArrayLinear3D.cs b/DesignTools/Operations/ArrayLinear3D.cs index 0bee9d492..e26bdd357 100644 --- a/DesignTools/Operations/ArrayLinear3D.cs +++ b/DesignTools/Operations/ArrayLinear3D.cs @@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools.EditableTypes; using MatterHackers.VectorMath; using System; using System.Linq; diff --git a/DesignTools/Operations/ArrayRadial3D.cs b/DesignTools/Operations/ArrayRadial3D.cs index f9a6ef079..edd5bacc2 100644 --- a/DesignTools/Operations/ArrayRadial3D.cs +++ b/DesignTools/Operations/ArrayRadial3D.cs @@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools.EditableTypes; using MatterHackers.VectorMath; using System; using System.ComponentModel; diff --git a/DesignTools/Operations/FitToBounds3D.cs b/DesignTools/Operations/FitToBounds3D.cs index b2a9c4b1f..3c9bbfcbe 100644 --- a/DesignTools/Operations/FitToBounds3D.cs +++ b/DesignTools/Operations/FitToBounds3D.cs @@ -52,8 +52,8 @@ namespace MatterHackers.MatterControl.DesignTools.Operations public FitType FitType { get; set; } = FitType.Box; public double Width { get; set; } - public double Diameter { get; set ; } public double Depth { get; set; } + public double Diameter { get; set; } public double Height { get; set; } [Description("Set the rules for how to maintain the part while scaling.")] @@ -74,6 +74,8 @@ namespace MatterHackers.MatterControl.DesignTools.Operations public override void Apply(UndoBuffer undoBuffer) { + SuspendRebuild(); + // push our matrix into our children foreach (var child in this.Children) { @@ -89,10 +91,15 @@ namespace MatterHackers.MatterControl.DesignTools.Operations list.Remove(this); list.AddRange(ScaleItem.Children); }); + + ResumeRebuild(); + Invalidate(new InvalidateArgs(this, InvalidateType.Content)); } public override void Remove(UndoBuffer undoBuffer) { + SuspendRebuild(); + // push our matrix into inner children foreach (var child in ScaleItem.Children) { @@ -105,6 +112,9 @@ namespace MatterHackers.MatterControl.DesignTools.Operations list.Remove(this); list.AddRange(ScaleItem.Children); }); + + ResumeRebuild(); + Invalidate(new InvalidateArgs(this, InvalidateType.Content)); } public override void OnInvalidate(InvalidateArgs invalidateType) diff --git a/DesignTools/Primitives/TextObject3D.cs b/DesignTools/Primitives/TextObject3D.cs index cacaeb0dd..86f117ac5 100644 --- a/DesignTools/Primitives/TextObject3D.cs +++ b/DesignTools/Primitives/TextObject3D.cs @@ -92,31 +92,31 @@ namespace MatterHackers.MatterControl.DesignTools SuspendRebuild(); var aabb = this.GetAxisAlignedBoundingBox(); - this.Children.Modify(list => + this.Children.Modify((list) => { list.Clear(); + + var offest = 0.0; + double pointsToMm = 0.352778; + foreach (var letter in NameToWrite.ToCharArray()) + { + var letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(Font), PointSize)) + { + ResolutionScale = 10 + }; + var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm)); + IObject3D letterObject = new Object3D() + { + Mesh = VertexSourceToMesh.Extrude(scalledLetterPrinter, Height) + }; + + letterObject.Matrix = Matrix4X4.CreateTranslation(offest, 0, 0); + list.Add(letterObject); + + offest += letterPrinter.GetSize(letter.ToString()).X * pointsToMm; + } }); - var offest = 0.0; - double pointsToMm = 0.352778; - foreach (var letter in NameToWrite.ToCharArray()) - { - var letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(Font), PointSize)) - { - ResolutionScale = 10 - }; - var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm)); - IObject3D letterObject = new Object3D() - { - Mesh = VertexSourceToMesh.Extrude(scalledLetterPrinter, Height) - }; - - letterObject.Matrix = Matrix4X4.CreateTranslation(offest, 0, 0); - this.Children.Add(letterObject); - - offest += letterPrinter.GetSize(letter.ToString()).X * pointsToMm; - } - if (aabb.ZSize > 0) { diff --git a/DesignTools/PublicPropertyEditor.cs b/DesignTools/PublicPropertyEditor.cs index 64ae3a65b..823376423 100644 --- a/DesignTools/PublicPropertyEditor.cs +++ b/DesignTools/PublicPropertyEditor.cs @@ -39,7 +39,7 @@ using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; -using MatterHackers.MatterControl.DesignTools.Operations; +using MatterHackers.MatterControl.DesignTools.EditableTypes; using MatterHackers.MatterControl.PartPreviewWindow; using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.VectorMath; @@ -86,7 +86,8 @@ namespace MatterHackers.MatterControl.DesignTools { typeof(double), typeof(int), typeof(char), typeof(string), typeof(bool), typeof(Vector2), typeof(Vector3), - typeof(DirectionVector), typeof(DirectionAxis) + typeof(DirectionVector), typeof(DirectionAxis), + typeof(ChildrenSelector) }; public const BindingFlags OwnedPropertiesOnly = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; @@ -147,6 +148,30 @@ namespace MatterHackers.MatterControl.DesignTools return rowContainer; } + private static FlowLayoutWidget CreateSettingsColumn(EditableProperty property) + { + return CreateSettingsColumn(property.DisplayName.Localize(), property.Description.Localize()); + } + + private static FlowLayoutWidget CreateSettingsColumn(string labelText, string toolTipText = null) + { + var columnContainer = new FlowLayoutWidget(FlowDirection.TopToBottom) + { + HAnchor = HAnchor.Stretch, + Padding = new BorderDouble(5), + ToolTipText = toolTipText + }; + + var label = new TextWidget(labelText + ":", pointSize: 11, textColor: ActiveTheme.Instance.PrimaryTextColor) + { + Margin = new BorderDouble(0, 3, 0, 0), + HAnchor = HAnchor.Left + }; + columnContainer.AddChild(label); + + return columnContainer; + } + public static IEnumerable GetEditablePropreties(IObject3D item) { return item.GetType().GetProperties(OwnedPropertiesOnly) @@ -399,6 +424,12 @@ namespace MatterHackers.MatterControl.DesignTools }; } } + else if (property.Value is ChildrenSelector childSelector) + { + rowContainer = CreateSettingsColumn(property); + rowContainer.AddChild(CreateSelector(childSelector, property.Item, theme)); + editControlsContainer.AddChild(rowContainer); + } // create a int editor else if (property.Value is int intValue) { @@ -499,6 +530,97 @@ namespace MatterHackers.MatterControl.DesignTools context.editRows.Add(property.PropertyInfo.Name, rowContainer); } + private static GuiWidget CreateSelector(ChildrenSelector childSelector, IObject3D parent, ThemeConfig theme) + { + GuiWidget tabContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); + + var children = parent.Children.ToList(); + + Dictionary objectChecks = new Dictionary(); + + List radioSiblings = new List(); + for (int i = 0; i < children.Count; i++) + { + var itemIndex = i; + var child = children[itemIndex]; + FlowLayoutWidget rowContainer = new FlowLayoutWidget(); + + GuiWidget selectWidget; + if (children.Count == 2) + { + var radioButton = new RadioButton(string.IsNullOrWhiteSpace(child.Name) ? $"{itemIndex}" : $"{child.Name}") + { + Checked = childSelector.Contains(child.ID), + TextColor = ActiveTheme.Instance.PrimaryTextColor + }; + radioSiblings.Add(radioButton); + radioButton.SiblingRadioButtonList = radioSiblings; + selectWidget = radioButton; + } + else + { + selectWidget = new CheckBox(string.IsNullOrWhiteSpace(child.Name) ? $"{itemIndex}" : $"{child.Name}") + { + Checked = childSelector.Contains(child.ID), + TextColor = ActiveTheme.Instance.PrimaryTextColor + }; + } + + objectChecks.Add((ICheckbox)selectWidget, child); + + rowContainer.AddChild(selectWidget); + ICheckbox checkBox = selectWidget as ICheckbox; + + checkBox.CheckedStateChanged += (s, e) => + { + if (s is ICheckbox checkbox) + { + if (checkBox.Checked) + { + if (!childSelector.Contains(objectChecks[checkbox].ID)) + { + childSelector.Add(objectChecks[checkbox].ID); + } + } + else + { + if (childSelector.Contains(objectChecks[checkbox].ID)) + { + childSelector.Remove(objectChecks[checkbox].ID); + } + } + } + }; + + tabContainer.AddChild(rowContainer); + } + + /* + bool operationApplied = parent.Descendants() + .Where((obj) => obj.OwnerID == parent.ID) + .Where((objId) => objId.Mesh != objId.Children.First().Mesh).Any(); + + bool selectionHasBeenMade = parent.Descendants() + .Where((obj) => obj.OwnerID == parent.ID && obj.OutputType == PrintOutputTypes.Hole) + .Any(); + + if (!operationApplied && !selectionHasBeenMade) + { + // select the last item + if (tabContainer.Descendants().Where((d) => d is ICheckbox).Last() is ICheckbox lastCheckBox) + { + lastCheckBox.Checked = true; + } + } + else + { + updateButton.Enabled = !operationApplied; + } + */ + + return tabContainer; + } + private void AddUnlockLinkIfRequired(PPEContext context, FlowLayoutWidget editControlsContainer, ThemeConfig theme) { var unlockLink = context.item.GetType().GetCustomAttributes(typeof(UnlockLinkAttribute), true).FirstOrDefault() as UnlockLinkAttribute; diff --git a/MatterControl.csproj b/MatterControl.csproj index 466914c07..3439d5e52 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -89,6 +89,8 @@ + + @@ -227,7 +229,6 @@ - diff --git a/PartPreviewWindow/View3D/Actions/CombineEditor.cs b/PartPreviewWindow/View3D/Actions/CombineEditor.cs index 34cfde4e1..7c81481ad 100644 --- a/PartPreviewWindow/View3D/Actions/CombineEditor.cs +++ b/PartPreviewWindow/View3D/Actions/CombineEditor.cs @@ -71,16 +71,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D var mainContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); if (group is CombineObject3D operationNode - && operationNode.Descendants().Where((obj) => obj.OwnerID == group.ID).All(c => c.OutputType != PrintOutputTypes.Hole)) + && operationNode.Descendants().Where((obj) => obj.OwnerID == group.ID).Any()) { - bool first = true; - // set all but one mesh to look like holes - foreach (var item in group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList()) - { - item.OutputType = first ? PrintOutputTypes.Solid : PrintOutputTypes.Hole; - first = false; - } - ProcessBooleans(group); } diff --git a/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs b/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs index 215fec2a7..3e3a3fdb4 100644 --- a/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs +++ b/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs @@ -70,19 +70,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D var mainContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); - if (group is IntersectionObject3D operationNode - && operationNode.Descendants().Where((obj) => obj.OwnerID == group.ID).All(c => c.OutputType != PrintOutputTypes.Hole)) - { - bool first = true; - // set all but one mesh to look like holes - foreach (var item in group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList()) - { - item.OutputType = first ? PrintOutputTypes.Solid : PrintOutputTypes.Hole; - first = false; - } - - ProcessBooleans(group); - } + ProcessBooleans(group); return mainContainer; } diff --git a/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs b/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs index ddb6f1ac1..3529ffbf5 100644 --- a/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs +++ b/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs @@ -137,7 +137,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { var radioButton = new RadioButton(string.IsNullOrWhiteSpace(item.Name) ? $"{itemIndex}" : $"{item.Name}") { - Checked = item.OutputType == PrintOutputTypes.Hole, TextColor = ActiveTheme.Instance.PrimaryTextColor }; radioSiblings.Add(radioButton); @@ -148,7 +147,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { selectWidget = new CheckBox(string.IsNullOrWhiteSpace(item.Name) ? $"{itemIndex}" : $"{item.Name}") { - Checked = item.OutputType == PrintOutputTypes.Hole, TextColor = ActiveTheme.Instance.PrimaryTextColor }; } @@ -161,11 +159,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D //group.ResetMeshWrappers(); // and set the output type for this checkbox - item.OutputType = checkBox.Checked ? PrintOutputTypes.Hole : PrintOutputTypes.Solid; - - int holeCount = children.Where((o) => o.OutputType == PrintOutputTypes.Hole).Count(); - int solidCount = children.Where((o) => o.OutputType != PrintOutputTypes.Hole).Count(); - updateButton.Enabled = children.Count != holeCount && children.Count != solidCount; }; tabContainer.AddChild(rowContainer); @@ -175,29 +168,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D .Where((obj) => obj.OwnerID == group.ID) .Where((objId) => objId.Mesh != objId.Children.First().Mesh).Any(); - bool selectionHasBeenMade = group.DescendantsAndSelf() - .Where((obj) => obj.OwnerID == group.ID && obj.OutputType == PrintOutputTypes.Hole) - .Any(); - - if (!operationApplied && !selectionHasBeenMade) - { - // select the last item - if (tabContainer.Descendants().Where((d) => d is ICheckbox).Last() is ICheckbox lastCheckBox) - { - lastCheckBox.Checked = true; - } - } - else - { - updateButton.Enabled = !operationApplied; - } - // add this last so it is at the bottom tabContainer.AddChild(updateButton); } private void ProcessBooleans(IObject3D group) { + /* // spin up a task to calculate the paint ApplicationController.Instance.Tasks.Execute("Subtract".Localize(), (reporter, cancellationToken) => { @@ -285,6 +262,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D return Task.CompletedTask; }); + */ } } } \ No newline at end of file diff --git a/PartPreviewWindow/View3D/Actions/SubtractEditor.cs b/PartPreviewWindow/View3D/Actions/SubtractEditor.cs deleted file mode 100644 index 55e57795c..000000000 --- a/PartPreviewWindow/View3D/Actions/SubtractEditor.cs +++ /dev/null @@ -1,179 +0,0 @@ -/* -Copyright (c) 2017, Lars Brubaker, John Lewin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MatterHackers.Agg; -using MatterHackers.Agg.UI; -using MatterHackers.DataConverters3D; -using MatterHackers.Localizations; - -namespace MatterHackers.MatterControl.PartPreviewWindow.View3D -{ - - public class SubtractEditor : IObject3DEditor - { - private SubtractObject3D subtractObject3D; - private View3DWidget view3DWidget; - public string Name => "Subtract"; - - public bool Unlocked { get; } = true; - - public GuiWidget Create(IObject3D group, View3DWidget view3DWidget, ThemeConfig theme) - { - this.view3DWidget = view3DWidget; - this.subtractObject3D = group as SubtractObject3D; - - var mainContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); - - if (group is SubtractObject3D) - { - AddSubtractSelector(view3DWidget, mainContainer, theme); - } - - return mainContainer; - } - - public IEnumerable SupportedTypes() => new Type[] - { - typeof(SubtractObject3D), - }; - - private void AddSubtractSelector(View3DWidget view3DWidget, FlowLayoutWidget tabContainer, ThemeConfig theme) - { - var children = subtractObject3D.Children.ToList(); - - tabContainer.AddChild(new TextWidget("Set Subtract") - { - TextColor = ActiveTheme.Instance.PrimaryTextColor, - HAnchor = HAnchor.Left, - AutoExpandBoundsToText = true, - }); - - Dictionary objectChecks = new Dictionary(); - // create this early so we can use enable disable it on button changed state - var updateButton = theme.ButtonFactory.Generate("Update".Localize()); - updateButton.Margin = new BorderDouble(5); - updateButton.HAnchor = HAnchor.Right; - updateButton.Click += (s, e) => - { - // make sure the mesh on the group is not visible - updateButton.Enabled = PrepareForSubtract(objectChecks); - updateButton.Enabled = false; - subtractObject3D.Rebuild(null); - }; - - List radioSiblings = new List(); - for (int i = 0; i < children.Count; i++) - { - var itemIndex = i; - var item = children[itemIndex]; - FlowLayoutWidget rowContainer = new FlowLayoutWidget(); - - GuiWidget selectWidget; - if (children.Count == 2) - { - var radioButton = new RadioButton(string.IsNullOrWhiteSpace(item.Name) ? $"{itemIndex}" : $"{item.Name}") - { - Checked = item.OutputType == PrintOutputTypes.Hole, - TextColor = ActiveTheme.Instance.PrimaryTextColor - }; - radioSiblings.Add(radioButton); - radioButton.SiblingRadioButtonList = radioSiblings; - selectWidget = radioButton; - } - else - { - selectWidget = new CheckBox(string.IsNullOrWhiteSpace(item.Name) ? $"{itemIndex}" : $"{item.Name}") - { - Checked = item.OutputType == PrintOutputTypes.Hole, - TextColor = ActiveTheme.Instance.PrimaryTextColor - }; - } - rowContainer.AddChild(selectWidget); - ICheckbox checkBox = selectWidget as ICheckbox; - - objectChecks.Add(item, checkBox); - - checkBox.CheckedStateChanged += (s, e) => - { - updateButton.Enabled = PrepareForSubtract(objectChecks); - }; - - tabContainer.AddChild(rowContainer); - } - - bool operationApplied = subtractObject3D.Descendants() - .Where((obj) => obj.OwnerID == subtractObject3D.ID) - .Where((objId) => objId.Mesh != objId.Children.First().Mesh).Any(); - - bool selectionHasBeenMade = subtractObject3D.Descendants() - .Where((obj) => obj.OwnerID == subtractObject3D.ID && obj.OutputType == PrintOutputTypes.Hole) - .Any(); - - if (!operationApplied && !selectionHasBeenMade) - { - // select the last item - if (tabContainer.Descendants().Where((d) => d is ICheckbox).Last() is ICheckbox lastCheckBox) - { - lastCheckBox.Checked = true; - } - } - else - { - updateButton.Enabled = !operationApplied; - } - - // add this last so it is at the bottom - tabContainer.AddChild(updateButton); - } - - private bool PrepareForSubtract(Dictionary objectChecks) - { - subtractObject3D.SuspendRebuild(); - // make sure the mesh on the group is not visible - subtractObject3D.ResetMeshWrapperMeshes(Object3DPropertyFlags.All, CancellationToken.None); - - foreach (var keyValue in objectChecks) - { - // and set the output type for this checkbox - keyValue.Key.OutputType = keyValue.Value.Checked ? PrintOutputTypes.Hole : PrintOutputTypes.Solid; - } - - int holeCount = objectChecks.Where((o) => o.Key.OutputType == PrintOutputTypes.Hole).Count(); - int solidCount = objectChecks.Where((o) => o.Key.OutputType != PrintOutputTypes.Hole).Count(); - - subtractObject3D.ResumeRebuild(); - return objectChecks.Count != holeCount && objectChecks.Count != solidCount; - } - } -} \ No newline at end of file diff --git a/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs b/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs index 25c834ec5..59902e30c 100644 --- a/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs +++ b/PartPreviewWindow/View3D/Actions/SubtractObject3D.cs @@ -31,6 +31,8 @@ using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools; +using MatterHackers.MatterControl.DesignTools.EditableTypes; using MatterHackers.PolygonMesh; using System; using System.Collections.Generic; @@ -40,69 +42,21 @@ using System.Threading.Tasks; namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { - public class SubtractObject3D : MeshWrapperObject3D + + public class SubtractObject3D : MeshWrapperObject3D, IPublicPropertyObject { public SubtractObject3D() { Name = "Subtract"; } - public override void OnInvalidate(InvalidateArgs invalidateType) - { - if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Content) - || invalidateType.InvalidateType.HasFlag(InvalidateType.Matrix) - || invalidateType.InvalidateType.HasFlag(InvalidateType.Mesh)) - && invalidateType.Source != this - && !RebuildSuspended) - { - Rebuild(null); - } - else - { - base.OnInvalidate(invalidateType); - } - } - - public override void Rebuild(UndoBuffer undoBuffer) - { - this.DebugDepth("Rebuild"); - SuspendRebuild(); - ResetMeshWrapperMeshes(Object3DPropertyFlags.All & (~Object3DPropertyFlags.OutputType), CancellationToken.None); - - // spin up a task to remove holes from the objects in the group - ApplicationController.Instance.Tasks.Execute( - "Subtract".Localize(), - (reporter, cancellationToken) => - { - var progressStatus = new ProgressStatus(); - reporter.Report(progressStatus); - - var removeObjects = this.Children - .Where((i) => i.WorldOutputType(this) == PrintOutputTypes.Hole) - .SelectMany((h) => h.DescendantsAndSelf()) - .Where((c) => c.OwnerID == this.ID).ToList(); - var keepObjects = this.Children - .Where((i) => i.WorldOutputType(this) != PrintOutputTypes.Hole) - .SelectMany((h) => h.DescendantsAndSelf()) - .Where((c) => c.OwnerID == this.ID).ToList(); - - Subtract(keepObjects, removeObjects, cancellationToken, reporter); - - ResumeRebuild(); - - UiThread.RunOnIdle(() => base.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh))); - - return Task.CompletedTask; - }); - - base.Rebuild(null); - } - public static void Subtract(List keepObjects, List removeObjects) { Subtract(keepObjects, removeObjects, CancellationToken.None, null); } + public ChildrenSelector ItemsToSubtract { get; set; } = new ChildrenSelector(); + public static void Subtract(List keepObjects, List removeObjects, CancellationToken cancellationToken, IProgress reporter) { if (removeObjects.Any() @@ -142,9 +96,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D inverse.Invert(); transformedKeep.Transform(inverse); + keep.SuspendRebuild(); keep.Mesh = transformedKeep; - // TODO: make this the subtract object when it is available - keep.Invalidate(new InvalidateArgs(keep, InvalidateType.Content)); + keep.ResumeRebuild(); percentCompleted += amountPerOperation; progressStatus.Progress0To1 = percentCompleted; @@ -155,5 +109,58 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D } } } + + public override void OnInvalidate(InvalidateArgs invalidateType) + { + if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Content) + || invalidateType.InvalidateType.HasFlag(InvalidateType.Matrix) + || invalidateType.InvalidateType.HasFlag(InvalidateType.Mesh)) + && invalidateType.Source != this + && !RebuildSuspended) + { + Rebuild(null); + } + else + { + base.OnInvalidate(invalidateType); + } + } + + public override void Rebuild(UndoBuffer undoBuffer) + { + this.DebugDepth("Rebuild"); + SuspendRebuild(); + ResetMeshWrapperMeshes(Object3DPropertyFlags.All, CancellationToken.None); + + // spin up a task to remove holes from the objects in the group + ApplicationController.Instance.Tasks.Execute( + "Subtract".Localize(), + (reporter, cancellationToken) => + { + var progressStatus = new ProgressStatus(); + reporter.Report(progressStatus); + + var removeObjects = this.Children + .Where((i) => ItemsToSubtract.Contains(i.ID)) + .SelectMany((h) => h.DescendantsAndSelf()) + .Where((c) => c.OwnerID == this.ID).ToList(); + var keepObjects = this.Children + .Where((i) => !ItemsToSubtract.Contains(i.ID)) + .SelectMany((h) => h.DescendantsAndSelf()) + .Where((c) => c.OwnerID == this.ID).ToList(); + + Subtract(keepObjects, removeObjects, cancellationToken, reporter); + + UiThread.RunOnIdle(() => + { + ResumeRebuild(); + base.Invalidate(new InvalidateArgs(this, InvalidateType.Content)); + }); + + return Task.CompletedTask; + }); + + base.Rebuild(null); + } } } \ No newline at end of file diff --git a/PartPreviewWindow/View3D/MeshViewerWidget.cs b/PartPreviewWindow/View3D/MeshViewerWidget.cs index a0d1f63dd..26b5edc1d 100644 --- a/PartPreviewWindow/View3D/MeshViewerWidget.cs +++ b/PartPreviewWindow/View3D/MeshViewerWidget.cs @@ -573,10 +573,6 @@ namespace MatterHackers.MeshVisualizer { drawColor = new Color(Color.Yellow, 120); } - else if (item.WorldOutputType() == PrintOutputTypes.Hole) - { - drawColor = new Color(Color.Gray, 120); - } // If there is a printer - check if the object is within the bed volume (has no AABB outside the bed volume) if (sceneContext.Printer != null) diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 0988c5226..b9b5f5904 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 0988c5226081c0928f3703fbe83b089d3bb250c2 +Subproject commit b9b5f59042a6404dd99a61a9e295f072ab6f915b diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 8b95e477f..5271ad98f 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 8b95e477f90a8dd7bfec5063bff45c9f1a4ba779 +Subproject commit 5271ad98f4e8a114a9f81c8f04b0e68065493483 diff --git a/Tests/MatterControl.Tests/SceneTests.cs b/Tests/MatterControl.Tests/SceneTests.cs index dbd942acc..4f2738602 100644 --- a/Tests/MatterControl.Tests/SceneTests.cs +++ b/Tests/MatterControl.Tests/SceneTests.cs @@ -186,12 +186,12 @@ namespace MatterHackers.PolygonMesh.UnitTests private readonly Matrix4X4 BlueMatrix = Matrix4X4.CreateTranslation(20, 0, 0); private readonly PrintOutputTypes RootOutputType = PrintOutputTypes.Solid; - private readonly PrintOutputTypes SuperGroupOutputType = PrintOutputTypes.Hole; + private readonly PrintOutputTypes SuperGroupOutputType = PrintOutputTypes.Solid; private readonly PrintOutputTypes GroupOutputType = PrintOutputTypes.Solid; private readonly PrintOutputTypes RedOutputType = PrintOutputTypes.Support; private readonly PrintOutputTypes GreenOutputType = PrintOutputTypes.Support; - private readonly PrintOutputTypes BlueOutputType = PrintOutputTypes.Hole; + private readonly PrintOutputTypes BlueOutputType = PrintOutputTypes.Solid; public InteractiveScene SampleScene() {