Merge pull request #3377 from larsbrubaker/design_tools

Subtract is working now
This commit is contained in:
Lars Brubaker 2018-06-01 17:52:52 -07:00 committed by GitHub
commit 797ee5d0bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 311 additions and 324 deletions

View file

@ -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; }
}
}

View file

@ -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; }
}
}

View file

@ -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)

View file

@ -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; }
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

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

View file

@ -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<EditableProperty> 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<ICheckbox, IObject3D> objectChecks = new Dictionary<ICheckbox, IObject3D>();
List<GuiWidget> radioSiblings = new List<GuiWidget>();
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;

View file

@ -89,6 +89,8 @@
<Compile Include="CustomWidgets\TreeView\TreeView.cs" />
<Compile Include="DesignTools\Attributes\ShowSearchFieldAttribute.cs" />
<Compile Include="DesignTools\Interfaces\IPublicPropertyObject.cs" />
<Compile Include="DesignTools\EditableTypes\DirectionAxis.cs" />
<Compile Include="DesignTools\EditableTypes\DirectionVector.cs" />
<Compile Include="DesignTools\Operations\Group3D.cs" />
<Compile Include="DesignTools\Operations\OperationSource.cs" />
<Compile Include="DesignTools\Operations\PinchObject3D.cs" />
@ -227,7 +229,6 @@
<Compile Include="PartPreviewWindow\Toolbar.cs" />
<Compile Include="PartPreviewWindow\View3D\Actions\IntersectionEditor.cs" />
<Compile Include="PartPreviewWindow\View3D\Actions\MeshWrapper.cs" />
<Compile Include="PartPreviewWindow\View3D\Actions\SubtractEditor.cs" />
<Compile Include="PartPreviewWindow\View3D\PrinterBar\CancelButton.cs" />
<Compile Include="PartPreviewWindow\View3D\PrinterBar\PauseResumeButton.cs" />
<Compile Include="Library\ReadOnlyStreamItem.cs" />

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
});
*/
}
}
}

View file

@ -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<Type> 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<IObject3D, ICheckbox> objectChecks = new Dictionary<IObject3D, ICheckbox>();
// 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<GuiWidget> radioSiblings = new List<GuiWidget>();
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<IObject3D, ICheckbox> 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;
}
}
}

View file

@ -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<IObject3D> keepObjects, List<IObject3D> removeObjects)
{
Subtract(keepObjects, removeObjects, CancellationToken.None, null);
}
public ChildrenSelector ItemsToSubtract { get; set; } = new ChildrenSelector();
public static void Subtract(List<IObject3D> keepObjects, List<IObject3D> removeObjects, CancellationToken cancellationToken, IProgress<ProgressStatus> 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);
}
}
}

View file

@ -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)

@ -1 +1 @@
Subproject commit 0988c5226081c0928f3703fbe83b089d3bb250c2
Subproject commit b9b5f59042a6404dd99a61a9e295f072ab6f915b

@ -1 +1 @@
Subproject commit 8b95e477f90a8dd7bfec5063bff45c9f1a4ba779
Subproject commit 5271ad98f4e8a114a9f81c8f04b0e68065493483

View file

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