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() {