diff --git a/ApplicationView/ApplicationController.cs b/ApplicationView/ApplicationController.cs index 809f71669..f6e88aae1 100644 --- a/ApplicationView/ApplicationController.cs +++ b/ApplicationView/ApplicationController.cs @@ -435,10 +435,10 @@ namespace MatterHackers.MatterControl TitleResolver = () => "Align".Localize(), Action = (scene) => { - scene.AddSelectionAsChildren(new ArangeObject3D()); - if(scene.SelectedItem is ArangeObject3D arange) + scene.AddSelectionAsChildren(new ArrangeObject3D()); + if(scene.SelectedItem is ArrangeObject3D arrange) { - arange.Rebuild(); + arrange.Rebuild(); } }, //Icon = AggContext.StaticData.LoadIcon("array_linear.png").SetPreMultiply(), diff --git a/ApplicationView/ThemeConfig.cs b/ApplicationView/ThemeConfig.cs index cc66c9b7e..55b857d4b 100644 --- a/ApplicationView/ThemeConfig.cs +++ b/ApplicationView/ThemeConfig.cs @@ -45,8 +45,8 @@ namespace MatterHackers.MatterControl { protected static readonly int DefaultScrollBarWidth = 120; - private static ImageBuffer restoreNormal; - private static ImageBuffer restoreHover; + public static ImageBuffer RestoreNormal { get; private set; } + public static ImageBuffer RestoreHover { get; private set; } private static ImageBuffer restorePressed; private readonly int fizedHeightA = (int)(25 * GuiWidget.DeviceScale + .5); @@ -140,13 +140,13 @@ namespace MatterHackers.MatterControl if (AggContext.OperatingSystem == OSType.Android) { - restoreNormal = ColorCircle(size, new Color(200, 0, 0)); + RestoreNormal = ColorCircle(size, new Color(200, 0, 0)); } else { - restoreNormal = ColorCircle(size, Color.Transparent); + RestoreNormal = ColorCircle(size, Color.Transparent); } - restoreHover = ColorCircle(size, new Color("#DB4437")); + RestoreHover = ColorCircle(size, new Color("#DB4437")); restorePressed = ColorCircle(size, new Color(255, 0, 0)); } @@ -375,10 +375,10 @@ namespace MatterHackers.MatterControl { return new Button( new ButtonViewStates( - new ImageWidget(restoreNormal), - new ImageWidget(restoreHover), + new ImageWidget(RestoreNormal), + new ImageWidget(RestoreHover), new ImageWidget(restorePressed), - new ImageWidget(restoreNormal))) + new ImageWidget(RestoreNormal))) { VAnchor = VAnchor.Center, Margin = new BorderDouble(0, 0, 5, 0) diff --git a/DesignTools/Operations/ArrangeObject3D.cs b/DesignTools/Operations/ArrangeObject3D.cs new file mode 100644 index 000000000..00bdb6b79 --- /dev/null +++ b/DesignTools/Operations/ArrangeObject3D.cs @@ -0,0 +1,186 @@ +/* +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 System; +using System.Collections.Generic; +using MatterHackers.DataConverters3D; +using MatterHackers.VectorMath; +using Newtonsoft.Json; + +namespace MatterHackers.MatterControl.DesignTools.Operations +{ + using Aabb = AxisAlignedBoundingBox; + + public class ArrangeObject3D : Object3D, IRebuildable + { + // We need to serialize this so we can remove the arrange and get back to the objects before arranging + public List ChildrenBounds = new List(); + + public ArrangeObject3D() + { + } + + public enum Align { None, Min, Center, Max } + + public override string ActiveEditor => "PublicPropertyEditor"; + + [Icons(new string[] {"align_left.png", "align_center_x.png", "align_right.png"})] + public Align XAlign { get; set; } = Align.None; + [Icons(new string[] { "align_left.png", "align_center_x.png", "align_right.png" })] + [EnableIf("XAlign", "!None")] + public Align XAlignTo { get; set; } = Align.None; + [EnableIf("XAlign", "!None")] + public double OffsetX { get; set; } = 0; + + public Align YAlign { get; set; } = Align.None; + public Align YAlignTo { get; set; } = Align.None; + public double YOffset { get; set; } = 0; + + public Align ZAlign { get; set; } = Align.None; + public Align ZAlignTo { get; set; } = Align.None; + public double ZOffset { get; set; } = 0; + + + public void Rebuild() + { + var aabb = this.GetAxisAlignedBoundingBox(); + + // TODO: check if the has code for the children + if (ChildrenBounds.Count == 0) + { + this.Children.Modify(list => + { + foreach (var child in list) + { + ChildrenBounds.Add(child.GetAxisAlignedBoundingBox()); + } + }); + } + + this.Children.Modify(list => + { + var firstBounds = ChildrenBounds[0]; + int i = 0; + foreach (var child in list) + { + if (i > 0) + { + if (XAlign == Align.None) + { + // make sure it is where it started + AlignAxis(0, Align.Min, ChildrenBounds[i].minXYZ.X, 0, child); + } + else + { + AlignAxis(0, XAlign, GetAlignToOffset(0, XAlignTo == Align.None ? XAlign : XAlignTo), OffsetX, child); + } + if (YAlign == Align.None) + { + AlignAxis(1, Align.Min, ChildrenBounds[i].minXYZ.Y, 0, child); + } + else + { + AlignAxis(1, YAlign, GetAlignToOffset(1, YAlignTo == Align.None ? YAlign : YAlignTo), YOffset, child); + } + if (ZAlign == Align.None) + { + AlignAxis(2, Align.Min, ChildrenBounds[i].minXYZ.Z, 0, child); + } + else + { + AlignAxis(2, ZAlign, GetAlignToOffset(2, ZAlignTo == Align.None ? ZAlign : ZAlignTo), ZOffset, child); + } + } + i++; + } + }); + } + + public override bool CanRemove => true; + public override bool CanBake => true; + + public override void Remove() + { + // put everything back to where it was before the arange started + if(ChildrenBounds.Count == Children.Count) + { + int i = 0; + foreach(var child in Children) + { + // Where you are minus where you started to get back to where you started + child.Translate(child.GetAxisAlignedBoundingBox().minXYZ - ChildrenBounds[i++].minXYZ); + } + } + + base.Remove(); + } + + private void AlignAxis(int axis, Align align, double alignTo, double offset, + IObject3D item) + { + var aabb = item.GetAxisAlignedBoundingBox(); + var translate = Vector3.Zero; + + switch (align) + { + case Align.Min: + translate[axis] = alignTo - aabb.minXYZ[axis] + offset; + break; + + case Align.Center: + translate[axis] = alignTo - aabb.Center[axis] + offset; + break; + + case Align.Max: + translate[axis] = alignTo - aabb.maxXYZ[axis] + offset; + break; + } + + item.Translate(translate); + } + + private double GetAlignToOffset(int axis, Align alignTo) + { + switch (alignTo) + { + case Align.Min: + return ChildrenBounds[0].minXYZ[axis]; + + case Align.Center: + return ChildrenBounds[0].Center[axis]; + + case Align.Max: + return ChildrenBounds[0].maxXYZ[axis]; + + default: + throw new NotImplementedException(); + } + } + } +} \ No newline at end of file diff --git a/DesignTools/Operations/ArrayAdvancedObject3D.cs b/DesignTools/Operations/ArrayAdvancedObject3D.cs new file mode 100644 index 000000000..df6602fda --- /dev/null +++ b/DesignTools/Operations/ArrayAdvancedObject3D.cs @@ -0,0 +1,98 @@ +/* +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 System.Linq; +using MatterHackers.DataConverters3D; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools.Operations +{ + public class ArrayAdvancedObject3D : Object3D, IRebuildable + { + public ArrayAdvancedObject3D() + { + } + + public override string ActiveEditor => "PublicPropertyEditor"; + public int Count { get; set; } = 3; + public double Rotate { get; set; } = 0; + public bool RotatePart { get; set; } = false; + public double Scale { get; set; } = 1; + public bool ScaleOffset { get; set; } = false; + public double XOffset { get; set; } = 30; + public double YOffset { get; set; } = 0; + + public void Rebuild() + { + this.Children.Modify(list => + { + IObject3D lastChild = list.First(); + list.Clear(); + list.Add(lastChild); + var offset = Vector3.Zero; + for (int i = 1; i < Count; i++) + { + var rotateRadians = MathHelper.DegreesToRadians(Rotate); + var nextOffset = new Vector2(XOffset, YOffset); + if (ScaleOffset) + { + for (int j = 1; j < i; j++) + { + nextOffset *= Scale; + } + } + + nextOffset.Rotate(rotateRadians * i); + var next = lastChild.Clone(); + next.Matrix *= Matrix4X4.CreateTranslation(nextOffset.X, nextOffset.Y, 0); + + if (RotatePart) + { + next.ApplyAtBoundsCenter(Matrix4X4.CreateRotationZ(rotateRadians)); + } + + next.ApplyAtBoundsCenter(Matrix4X4.CreateScale(Scale)); + list.Add(next); + lastChild = next; + } + }); + } + } + + 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/ArrayLinearObject3D.cs b/DesignTools/Operations/ArrayLinearObject3D.cs new file mode 100644 index 000000000..ff58a53a2 --- /dev/null +++ b/DesignTools/Operations/ArrayLinearObject3D.cs @@ -0,0 +1,65 @@ +/* +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 System.Linq; +using MatterHackers.DataConverters3D; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools.Operations +{ + public class ArrayLinearObject3D : Object3D, IRebuildable + { + public ArrayLinearObject3D() + { + } + + public override string ActiveEditor => "PublicPropertyEditor"; + public int Count { get; set; } = 3; + public DirectionVector Direction { get; set; } = new DirectionVector { Normal = new Vector3(1, 0, 0) }; + public double Distance { get; set; } = 30; + + public void Rebuild() + { + this.Children.Modify(list => + { + IObject3D lastChild = list.First(); + list.Clear(); + list.Add(lastChild); + var offset = Vector3.Zero; + for (int i = 1; i < Count; i++) + { + var next = lastChild.Clone(); + next.Matrix *= Matrix4X4.CreateTranslation(Direction.Normal.GetNormal() * Distance); + list.Add(next); + lastChild = next; + } + }); + } + } +} \ No newline at end of file diff --git a/DesignTools/Operations/ArrayObject3D.cs b/DesignTools/Operations/ArrayObject3D.cs deleted file mode 100644 index cdca2a255..000000000 --- a/DesignTools/Operations/ArrayObject3D.cs +++ /dev/null @@ -1,314 +0,0 @@ -/* -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 System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using MatterHackers.DataConverters3D; -using MatterHackers.VectorMath; -using Newtonsoft.Json; - -namespace MatterHackers.MatterControl.DesignTools.Operations -{ - using Aabb = AxisAlignedBoundingBox; - - public class ArangeObject3D : Object3D, IRebuildable - { - [JsonIgnoreAttribute] - private List childrenBounds = new List(); - - public ArangeObject3D() - { - } - - public enum Align { None, Min, Center, Max } - - public override string ActiveEditor => "PublicPropertyEditor"; - // Attributes - [SameLineAsLast, Icons(new string[] {"LeftX", "CenterX", "RightX"})] - public Align XAlign { get; set; } = Align.None; - // Attributes - [EnableIfNot("XAlign", "None"), Icons(new string[] {"NoneX", "LeftX", "CenterX", "RightX"})] - public Align XAlignTo { get; set; } = Align.None; - // Attributes - [EnableIfNot("XAlign", "None")] - public double OffsetX { get; set; } = 0; - - public Align YAlign { get; set; } = Align.None; - public Align YAlignTo { get; set; } = Align.None; - public double YOffset { get; set; } = 0; - - public Align ZAlign { get; set; } = Align.None; - public Align ZAlignTo { get; set; } = Align.None; - public double ZOffset { get; set; } = 0; - - - public void Rebuild() - { - var aabb = this.GetAxisAlignedBoundingBox(); - - // TODO: check if the has code for the children - if (childrenBounds.Count == 0) - { - this.Children.Modify(list => - { - foreach (var child in list) - { - childrenBounds.Add(child.GetAxisAlignedBoundingBox()); - } - }); - } - - this.Children.Modify(list => - { - var firstBounds = childrenBounds[0]; - int i = 0; - foreach (var child in list) - { - if (i > 0) - { - if (XAlign == Align.None) - { - // make sure it is where it started - AlignAxis(0, Align.Min, childrenBounds[i].minXYZ.X, 0, child); - } - else - { - AlignAxis(0, XAlign, GetAlignToOffset(0, XAlignTo == Align.None ? XAlign : XAlignTo), OffsetX, child); - } - if (YAlign == Align.None) - { - AlignAxis(1, Align.Min, childrenBounds[i].minXYZ.Y, 0, child); - } - else - { - AlignAxis(1, YAlign, GetAlignToOffset(1, YAlignTo == Align.None ? YAlign : YAlignTo), YOffset, child); - } - if (ZAlign == Align.None) - { - AlignAxis(2, Align.Min, childrenBounds[i].minXYZ.Z, 0, child); - } - else - { - AlignAxis(2, ZAlign, GetAlignToOffset(2, ZAlignTo == Align.None ? ZAlign : ZAlignTo), ZOffset, child); - } - } - i++; - } - }); - } - - private void AlignAxis(int axis, Align align, double alignTo, double offset, - IObject3D item) - { - var aabb = item.GetAxisAlignedBoundingBox(); - var translate = Vector3.Zero; - - switch (align) - { - case Align.Min: - translate[axis] = alignTo - aabb.minXYZ[axis] + offset; - break; - - case Align.Center: - translate[axis] = alignTo - aabb.Center[axis] + offset; - break; - - case Align.Max: - translate[axis] = alignTo - aabb.maxXYZ[axis] + offset; - break; - } - - item.Translate(translate); - } - - private double GetAlignToOffset(int axis, Align alignTo) - { - switch (alignTo) - { - case Align.Min: - return childrenBounds[0].minXYZ[axis]; - - case Align.Center: - return childrenBounds[0].Center[axis]; - - case Align.Max: - return childrenBounds[0].maxXYZ[axis]; - - default: - throw new NotImplementedException(); - } - } - } - - public class ArrayAdvancedObject3D : Object3D, IRebuildable - { - public ArrayAdvancedObject3D() - { - } - - public override string ActiveEditor => "PublicPropertyEditor"; - public int Count { get; set; } = 3; - public double Rotate { get; set; } = 0; - public bool RotatePart { get; set; } = false; - public double Scale { get; set; } = 1; - public bool ScaleOffset { get; set; } = false; - public double XOffset { get; set; } = 30; - public double YOffset { get; set; } = 0; - - public void Rebuild() - { - this.Children.Modify(list => - { - IObject3D lastChild = list.First(); - list.Clear(); - list.Add(lastChild); - var offset = Vector3.Zero; - for (int i = 1; i < Count; i++) - { - var rotateRadians = MathHelper.DegreesToRadians(Rotate); - var nextOffset = new Vector2(XOffset, YOffset); - if (ScaleOffset) - { - for (int j = 1; j < i; j++) - { - nextOffset *= Scale; - } - } - - nextOffset.Rotate(rotateRadians * i); - var next = lastChild.Clone(); - next.Matrix *= Matrix4X4.CreateTranslation(nextOffset.X, nextOffset.Y, 0); - - if (RotatePart) - { - next.ApplyAtBoundsCenter(Matrix4X4.CreateRotationZ(rotateRadians)); - } - - next.ApplyAtBoundsCenter(Matrix4X4.CreateScale(Scale)); - list.Add(next); - lastChild = next; - } - }); - } - } - - public class ArrayLinearObject3D : Object3D, IRebuildable - { - public ArrayLinearObject3D() - { - } - - public override string ActiveEditor => "PublicPropertyEditor"; - public int Count { get; set; } = 3; - public DirectionVector Direction { get; set; } = new DirectionVector { Normal = new Vector3(1, 0, 0) }; - public double Distance { get; set; } = 30; - - public void Rebuild() - { - this.Children.Modify(list => - { - IObject3D lastChild = list.First(); - list.Clear(); - list.Add(lastChild); - var offset = Vector3.Zero; - for (int i = 1; i < Count; i++) - { - var next = lastChild.Clone(); - next.Matrix *= Matrix4X4.CreateTranslation(Direction.Normal.GetNormal() * Distance); - list.Add(next); - lastChild = next; - } - }); - } - } - - public class ArrayRadialObject3D : Object3D, IRebuildable - { - public ArrayRadialObject3D() - { - } - - public override string ActiveEditor => "PublicPropertyEditor"; - public double Angle { get; set; } = 360; - public DirectionAxis Axis { get; set; } = new DirectionAxis() { Origin = Vector3.NegativeInfinity, Normal = Vector3.UnitZ }; - public int Count { get; set; } = 3; - - [DisplayName("Keep Within Angle")] - [Description("Keep the entire extents of the part within the angle described.")] - public bool KeepInAngle { get; set; } = false; - - [DisplayName("Rotate Part")] - [Description("Rotate the part to the same angle as the array.")] - public bool RotatePart { get; set; } = true; - - public void Rebuild() - { - if (Axis.Origin.X == double.NegativeInfinity) - { - // make it something reasonable (just to the left of the aabb of the object) - var aabb = this.GetAxisAlignedBoundingBox(); - Axis.Origin = new Vector3(aabb.minXYZ.X - aabb.XSize / 2, aabb.Center.Y, 0); - } - this.Children.Modify(list => - { - IObject3D first = list.First(); - - list.Clear(); - list.Add(first); - var offset = Vector3.Zero; - for (int i = 1; i < Count; i++) - { - var next = first.Clone(); - - var normal = Axis.Normal.GetNormal(); - var angleRadians = MathHelper.DegreesToRadians(Angle) / Count * i; - next.Rotate(Axis.Origin, normal, angleRadians); - - if (!RotatePart) - { - next.Rotate(next.GetAxisAlignedBoundingBox().Center, normal, -angleRadians); - } - - list.Add(next); - } - }); - this.Invalidate(); - } - } - - 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/ArrayRadialObject3D.cs b/DesignTools/Operations/ArrayRadialObject3D.cs new file mode 100644 index 000000000..1034e585a --- /dev/null +++ b/DesignTools/Operations/ArrayRadialObject3D.cs @@ -0,0 +1,90 @@ +/* +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 System.ComponentModel; +using System.Linq; +using MatterHackers.DataConverters3D; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools.Operations +{ + public class ArrayRadialObject3D : Object3D, IRebuildable + { + public ArrayRadialObject3D() + { + } + + public override string ActiveEditor => "PublicPropertyEditor"; + public double Angle { get; set; } = 360; + public DirectionAxis Axis { get; set; } = new DirectionAxis() { Origin = Vector3.NegativeInfinity, Normal = Vector3.UnitZ }; + public int Count { get; set; } = 3; + + [DisplayName("Keep Within Angle")] + [Description("Keep the entire extents of the part within the angle described.")] + public bool KeepInAngle { get; set; } = false; + + [DisplayName("Rotate Part")] + [Description("Rotate the part to the same angle as the array.")] + public bool RotatePart { get; set; } = true; + + public void Rebuild() + { + if (Axis.Origin.X == double.NegativeInfinity) + { + // make it something reasonable (just to the left of the aabb of the object) + var aabb = this.GetAxisAlignedBoundingBox(); + Axis.Origin = new Vector3(aabb.minXYZ.X - aabb.XSize / 2, aabb.Center.Y, 0); + } + this.Children.Modify(list => + { + IObject3D first = list.First(); + + list.Clear(); + list.Add(first); + var offset = Vector3.Zero; + for (int i = 1; i < Count; i++) + { + var next = first.Clone(); + + var normal = Axis.Normal.GetNormal(); + var angleRadians = MathHelper.DegreesToRadians(Angle) / Count * i; + next.Rotate(Axis.Origin, normal, angleRadians); + + if (!RotatePart) + { + next.Rotate(next.GetAxisAlignedBoundingBox().Center, normal, -angleRadians); + } + + list.Add(next); + } + }); + this.Invalidate(); + } + } +} \ No newline at end of file diff --git a/DesignTools/Operations/Object3DExtensions.cs b/DesignTools/Operations/Object3DExtensions.cs index 8a8631547..b5c901f5d 100644 --- a/DesignTools/Operations/Object3DExtensions.cs +++ b/DesignTools/Operations/Object3DExtensions.cs @@ -114,22 +114,6 @@ namespace MatterHackers.MatterControl.DesignTools.Operations scene.SelectedItem = wrapper; } - public static void Unwrap(this IObject3D item, InteractiveScene scene) - { - foreach (var child in item.Children) - { - child.Matrix *= item.Matrix; - } - - item.Parent.Children.Modify(list => - { - list.Remove(item); - list.AddRange(item.Children); - }); - - scene.SelectedItem = null; - } - public static void ApplyAtBoundsCenter(this IObject3D object3DToApplayTo, Matrix4X4 transformToApply) { object3DToApplayTo.Matrix = ApplyAtCenter(object3DToApplayTo.GetAxisAlignedBoundingBox(Matrix4X4.Identity), object3DToApplayTo.Matrix, transformToApply); diff --git a/DesignTools/Primitives/CubeObject3D.cs b/DesignTools/Primitives/CubeObject3D.cs index 5b1b93e09..0a006d8d1 100644 --- a/DesignTools/Primitives/CubeObject3D.cs +++ b/DesignTools/Primitives/CubeObject3D.cs @@ -27,10 +27,8 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -using System.Threading; using MatterHackers.DataConverters3D; using MatterHackers.PolygonMesh; -using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.DesignTools { @@ -140,9 +138,9 @@ public class ChairFoot2 : MatterCadObject3D public override string ActiveEditor => "PublicPropertyEditor"; - public double Width { get; set; } = 20; public double Depth { get; set; } = 20; public double Height { get; set; } = 20; + public double Width { get; set; } = 20; public static CubeObject3D Create() { diff --git a/DesignTools/PublicPropertyEditor.cs b/DesignTools/PublicPropertyEditor.cs index b45093552..2cb8423d9 100644 --- a/DesignTools/PublicPropertyEditor.cs +++ b/DesignTools/PublicPropertyEditor.cs @@ -54,6 +54,28 @@ namespace MatterHackers.MatterControl.DesignTools { } + [AttributeUsage(AttributeTargets.Property)] + public class EnableIfAttribute : Attribute + { + public string PropertyName { get; private set; } + public string ExpectedValue { get; private set; } + public EnableIfAttribute(string propertyName, string expectedValue) + { + this.PropertyName = propertyName; + this.ExpectedValue = expectedValue; + } + } + + [AttributeUsage(AttributeTargets.Property)] + public class IconsAttribute : Attribute + { + public string[] IconPaths { get; private set; } + public IconsAttribute(string[] iconPaths) + { + this.IconPaths = iconPaths; + } + } + public class PublicPropertyEditor : IObject3DEditor { private IObject3D item; @@ -342,43 +364,12 @@ namespace MatterHackers.MatterControl.DesignTools rowContainer.AddChild(textEditWidget); editControlsContainer.AddChild(rowContainer); } - // create a enum editor + // create an enum editor else if (property.PropertyType.IsEnum) { - // Enum keyed on name to friendly name - var enumItems = Enum.GetNames(property.PropertyType).Select(enumName => - { - return new - { - Key = enumName, - Value = enumName.Replace('_', ' ') - }; - }); - - FlowLayoutWidget rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize); - - var sortableAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); - var orderedItems = sortableAttribute != null ? enumItems.OrderBy(n => n.Value) : enumItems; - - foreach (var orderItem in orderedItems) - { - MenuItem newItem = dropDownList.AddItem(orderItem.Value); - - var localOredrItem = orderItem; - newItem.Selected += (sender, e) => - { - property.PropertyInfo.GetSetMethod().Invoke( - this.item, - new Object[] { Enum.Parse(property.PropertyType, localOredrItem.Key) }); - rebuildable?.Rebuild(); - }; - } - - dropDownList.SelectedLabel = property.Value.ToString().Replace('_', ' '); - rowContainer.AddChild(dropDownList); - editControlsContainer.AddChild(rowContainer); + editControlsContainer.AddChild(CreateEnumEditor(rebuildable, + property.PropertyInfo, property.PropertyType, property.Value, property.DisplayName, + theme)); } } @@ -391,5 +382,46 @@ namespace MatterHackers.MatterControl.DesignTools }; editControlsContainer.AddChild(updateButton); } + + private GuiWidget CreateEnumEditor(IRebuildable item, + PropertyInfo propertyInfo, Type propertyType, object value, string displayName, + ThemeConfig theme) + { + // Enum keyed on name to friendly name + var enumItems = Enum.GetNames(propertyType).Select(enumName => + { + return new + { + Key = enumName, + Value = enumName.Replace('_', ' ') + }; + }); + + FlowLayoutWidget rowContainer = CreateSettingsRow(displayName); + + var dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize); + + var sortableAttribute = propertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); + var orderedItems = sortableAttribute != null ? enumItems.OrderBy(n => n.Value) : enumItems; + + foreach (var orderItem in orderedItems) + { + MenuItem newItem = dropDownList.AddItem(orderItem.Value); + + var localOredrItem = orderItem; + newItem.Selected += (sender, e) => + { + propertyInfo.GetSetMethod().Invoke( + this.item, + new Object[] { Enum.Parse(propertyType, localOredrItem.Key) }); + item?.Rebuild(); + }; + } + + dropDownList.SelectedLabel = value.ToString().Replace('_', ' '); + rowContainer.AddChild(dropDownList); + + return rowContainer; + } } } \ No newline at end of file diff --git a/DesignTools/TestParts/BendOperation.cs b/DesignTools/TestParts/BendOperation.cs index a4a63a8f8..ac0db7442 100644 --- a/DesignTools/TestParts/BendOperation.cs +++ b/DesignTools/TestParts/BendOperation.cs @@ -38,7 +38,7 @@ namespace MatterHackers.MatterControl.DesignTools scene.SelectedItem = operationContainer; // wrap all the meshes with replacement meshes - foreach(var meshChild in child.Descendants().Where(x => x.Mesh != null).ToList()) + foreach(var meshChild in child.DescendantsAndSelf().Where(x => x.Mesh != null).ToList()) { var parent = meshChild.Parent; @@ -62,7 +62,7 @@ namespace MatterHackers.MatterControl.DesignTools { if(AngleDegrees > 0) { - foreach (var meshChild in operationContainer.Descendants().Where(x => x.OwnerID == operationContainer.ID)) + foreach (var meshChild in operationContainer.DescendantsAndSelf().Where(x => x.OwnerID == operationContainer.ID)) { var firstChild = meshChild.Children.First(); diff --git a/LocalizedString.cs b/LocalizedString.cs index 08a99be7c..4fa636670 100644 --- a/LocalizedString.cs +++ b/LocalizedString.cs @@ -44,6 +44,7 @@ namespace MatterHackers.Localizations if (MatterControlTranslationMap == null) { MatterControlTranslationMap = new TranslationMap("Translations", UserSettings.Instance.Language); + TranslationMap.ActiveTranslationMap = MatterControlTranslationMap; } } } @@ -52,10 +53,5 @@ namespace MatterHackers.Localizations { MatterControlTranslationMap = new TranslationMap("Translations", UserSettings.Instance.Language); } - - public static string Localize(this string englishString) - { - return MatterControlTranslationMap.Translate(englishString); - } } } \ No newline at end of file diff --git a/MatterControl.csproj b/MatterControl.csproj index f457bd6c8..f06a68c6b 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -86,9 +86,12 @@ + + + + - diff --git a/PartPreviewWindow/SelectedObjectPanel.cs b/PartPreviewWindow/SelectedObjectPanel.cs index f0ed09875..0e5b39784 100644 --- a/PartPreviewWindow/SelectedObjectPanel.cs +++ b/PartPreviewWindow/SelectedObjectPanel.cs @@ -42,6 +42,7 @@ using MatterHackers.MatterControl.DesignTools.Operations; using System.Reflection; using MatterHackers.VectorMath; using MatterHackers.Agg.Image; +using MatterHackers.Agg.Platform; namespace MatterHackers.MatterControl.PartPreviewWindow { @@ -61,7 +62,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow private Dictionary> objectEditorsByType; private SectionWidget editorSection; private TextButton editButton; - private TextButton removeButton; private GuiWidget editorPanel; private InlineTitleEdit inlineTitleEdit; @@ -188,17 +188,34 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }; toolbar.AddChild(editButton); - removeButton = new TextButton("Remove".Localize(), theme) + // put in a bake button + var icon = AggContext.StaticData.LoadIcon("bake.png", 16, 16).SetPreMultiply(); + var bakeButton = new IconButton(icon, theme) { - BackgroundColor = theme.MinimalShade, - Margin = theme.ButtonSpacing + Margin = theme.ButtonSpacing, + ToolTipText = "Bake operation into parts".Localize() }; - removeButton.Click += async (s, e) => + bakeButton.Click += (s, e) => { - this.item.Unwrap(printer.Bed.Scene); + scene.SelectedItem = null; + this.item.Bake(); }; - toolbar.AddChild(removeButton); + scene.SelectionChanged += (s, e) => bakeButton.Enabled = scene.SelectedItem?.CanBake == true; + toolbar.AddChild(bakeButton); + // put in a remove button + var removeButton = new IconButton(ThemeConfig.RestoreNormal, theme) + { + Margin = theme.ButtonSpacing, + ToolTipText = "Remove operation from parts".Localize() + }; + removeButton.Click += (s, e) => + { + scene.SelectedItem = null; + this.item.Remove(); + }; + scene.SelectionChanged += (s, e) => removeButton.Enabled = scene.SelectedItem?.CanRemove == true; + toolbar.AddChild(removeButton); // Add container used to host the current specialized editor for the selection editorColumn.AddChild(editorPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) diff --git a/PartPreviewWindow/View3D/Actions/CombineEditor.cs b/PartPreviewWindow/View3D/Actions/CombineEditor.cs index 881fe692f..b1077ffc1 100644 --- a/PartPreviewWindow/View3D/Actions/CombineEditor.cs +++ b/PartPreviewWindow/View3D/Actions/CombineEditor.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { bool first = true; // set all but one mesh to look like holes - foreach (var item in group.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList()) + foreach (var item in group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList()) { item.OutputType = first ? PrintOutputTypes.Solid : PrintOutputTypes.Hole; first = false; @@ -84,7 +84,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D reporter.Report(progressStatus); - var participants = group.Descendants().Where((obj) => obj.OwnerID == group.ID); + var participants = group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID); if (participants.Count() > 1) { diff --git a/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs b/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs index 88b155e04..5be76c382 100644 --- a/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs +++ b/PartPreviewWindow/View3D/Actions/IntersectionEditor.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { bool first = true; // set all but one mesh to look like holes - foreach (var item in group.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList()) + foreach (var item in group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList()) { item.OutputType = first ? PrintOutputTypes.Solid : PrintOutputTypes.Hole; first = false; @@ -84,7 +84,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D reporter.Report(progressStatus); - var participants = group.Descendants().Where((obj) => obj.OwnerID == group.ID); + var participants = group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID); if (participants.Count() > 1) { diff --git a/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs b/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs index c0887efdd..5bd6ea2fd 100644 --- a/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs +++ b/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs @@ -65,7 +65,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D public void ResetMeshWrappers() { this.Mesh = null; - var participants = this.Descendants().Where(o => o.OwnerID == this.ID).ToList(); + var participants = this.DescendantsAndSelf().Where(o => o.OwnerID == this.ID).ToList(); foreach (var item in participants) { item.Visible = true; diff --git a/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs b/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs index b1da8961f..5a9f04d70 100644 --- a/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs +++ b/PartPreviewWindow/View3D/Actions/SubtractAndReplace.cs @@ -146,14 +146,14 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D // make sure the mesh on the group is not visible group.ResetMeshWrappers(); - var wrappedItems = item.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList(); + var wrappedItems = item.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList(); foreach (var meshWrapper in wrappedItems) { // and set the output type for this checkbox meshWrapper.OutputType = checkBox.Checked ? PrintOutputTypes.Hole : PrintOutputTypes.Solid; } - var allItems = group.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList(); + var allItems = group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList(); int holeCount = allItems.Where((o) => o.OutputType == PrintOutputTypes.Hole).Count(); int solidCount = allItems.Where((o) => o.OutputType != PrintOutputTypes.Hole).Count(); updateButton.Enabled = allItems.Count() != holeCount && allItems.Count() != solidCount; @@ -162,11 +162,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D tabContainer.AddChild(rowContainer); } - bool operationApplied = group.Descendants() + bool operationApplied = group.DescendantsAndSelf() .Where((obj) => obj.OwnerID == group.ID) .Where((objId) => objId.Mesh != objId.Children.First().Mesh).Any(); - bool selectionHasBeenMade = group.Descendants() + bool selectionHasBeenMade = group.DescendantsAndSelf() .Where((obj) => obj.OwnerID == group.ID && obj.OutputType == PrintOutputTypes.Hole) .Any(); @@ -199,7 +199,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D reporter.Report(progressStatus); - var participants = group.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList(); + var participants = group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList(); var paintObjects = participants.Where((obj) => obj.OutputType == PrintOutputTypes.Hole).ToList(); var keepObjects = participants.Where((obj) => obj.OutputType != PrintOutputTypes.Hole).ToList(); diff --git a/PartPreviewWindow/View3D/Actions/SubtractEditor.cs b/PartPreviewWindow/View3D/Actions/SubtractEditor.cs index 3b7a39994..3f473c796 100644 --- a/PartPreviewWindow/View3D/Actions/SubtractEditor.cs +++ b/PartPreviewWindow/View3D/Actions/SubtractEditor.cs @@ -127,14 +127,14 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D // make sure the mesh on the group is not visible group.ResetMeshWrappers(); - var wrappedItems = item.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList(); + var wrappedItems = item.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList(); foreach (var meshWrapper in wrappedItems) { // and set the output type for this checkbox meshWrapper.OutputType = checkBox.Checked ? PrintOutputTypes.Hole : PrintOutputTypes.Solid; } - var allItems = group.Descendants().Where((obj) => obj.OwnerID == group.ID).ToList(); + var allItems = group.DescendantsAndSelf().Where((obj) => obj.OwnerID == group.ID).ToList(); int holeCount = allItems.Where((o) => o.OutputType == PrintOutputTypes.Hole).Count(); int solidCount = allItems.Where((o) => o.OutputType != PrintOutputTypes.Hole).Count(); updateButton.Enabled = allItems.Count != holeCount && allItems.Count != solidCount; @@ -143,11 +143,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D tabContainer.AddChild(rowContainer); } - bool operationApplied = group.Descendants() + bool operationApplied = group.DescendantsAndSelf() .Where((obj) => obj.OwnerID == group.ID) .Where((objId) => objId.Mesh != objId.Children.First().Mesh).Any(); - bool selectionHasBeenMade = group.Descendants() + bool selectionHasBeenMade = group.DescendantsAndSelf() .Where((obj) => obj.OwnerID == group.ID && obj.OutputType == PrintOutputTypes.Hole) .Any(); @@ -180,7 +180,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D reporter.Report(progressStatus); - var participants = group.Descendants().Where(o => o.OwnerID == group.ID).ToList(); + var participants = group.DescendantsAndSelf().Where(o => o.OwnerID == group.ID).ToList(); var removeObjects = participants.Where((obj) => obj.OutputType == PrintOutputTypes.Hole).ToList(); var keepObjects = participants.Where((obj) => obj.OutputType != PrintOutputTypes.Hole).ToList(); diff --git a/PartPreviewWindow/View3D/SceneActions.cs b/PartPreviewWindow/View3D/SceneActions.cs index 12a2595c7..305b55c92 100644 --- a/PartPreviewWindow/View3D/SceneActions.cs +++ b/PartPreviewWindow/View3D/SceneActions.cs @@ -173,7 +173,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { var clonedItem = item.Clone(); // make the name unique - var newName = agg_basics.GetNonCollidingName(item.Name, Scene.Descendants().Select((d) => d.Name)); + var newName = agg_basics.GetNonCollidingName(item.Name, Scene.DescendantsAndSelf().Select((d) => d.Name)); clonedItem.Name = newName; // add it to the scene Scene.Children.Add(clonedItem); @@ -186,7 +186,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var clonedItem = sourceItem.Clone(); // make the name unique - var newName = agg_basics.GetNonCollidingName(sourceItem.Name, Scene.Descendants().Select((d) => d.Name)); + var newName = agg_basics.GetNonCollidingName(sourceItem.Name, Scene.DescendantsAndSelf().Select((d) => d.Name)); clonedItem.Name = newName; // More useful if it creates the part in the exact position and then the user can move it. @@ -341,11 +341,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow PlatingHelper.PlaceOnBed(objectToLayFlatGroup); } - internal class ArangeUndoCommand : IUndoRedoCommand + internal class ArrangeUndoCommand : IUndoRedoCommand { private List allUndoTransforms = new List(); - public ArangeUndoCommand(View3DWidget view3DWidget, List preArrangeTarnsforms, List postArrangeTarnsforms) + public ArrangeUndoCommand(View3DWidget view3DWidget, List preArrangeTarnsforms, List postArrangeTarnsforms) { for (int i = 0; i < preArrangeTarnsforms.Count; i++) { diff --git a/PartPreviewWindow/View3D/UndoCommands/GroupCommand.cs b/PartPreviewWindow/View3D/UndoCommands/GroupCommand.cs index 5b166a2eb..62cb26be6 100644 --- a/PartPreviewWindow/View3D/UndoCommands/GroupCommand.cs +++ b/PartPreviewWindow/View3D/UndoCommands/GroupCommand.cs @@ -29,6 +29,7 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; +using MatterHackers.Localizations; using MatterHackers.MeshVisualizer; namespace MatterHackers.MatterControl.PartPreviewWindow @@ -51,7 +52,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { // This is the original do() case. The selection needs to be changed into a group and selected // change it to a standard group - var newGroup = new Object3D(); + var newGroup = new Object3D() + { + Name = "Group".Localize() + }; newGroup.Children.Modify((gChildren) => { selectedItem.Children.Modify((sChildren) => diff --git a/StaticData/Icons/align_Top.png b/StaticData/Icons/align_Top.png new file mode 100644 index 000000000..cd50145b5 Binary files /dev/null and b/StaticData/Icons/align_Top.png differ diff --git a/StaticData/Icons/align_bottom.png b/StaticData/Icons/align_bottom.png new file mode 100644 index 000000000..e3cf8aeb9 Binary files /dev/null and b/StaticData/Icons/align_bottom.png differ diff --git a/StaticData/Icons/align_center_x.png b/StaticData/Icons/align_center_x.png new file mode 100644 index 000000000..07e848152 Binary files /dev/null and b/StaticData/Icons/align_center_x.png differ diff --git a/StaticData/Icons/align_center_y.png b/StaticData/Icons/align_center_y.png new file mode 100644 index 000000000..0b2efeba4 Binary files /dev/null and b/StaticData/Icons/align_center_y.png differ diff --git a/StaticData/Icons/align_left.png b/StaticData/Icons/align_left.png new file mode 100644 index 000000000..f1b5d5228 Binary files /dev/null and b/StaticData/Icons/align_left.png differ diff --git a/StaticData/Icons/align_right.png b/StaticData/Icons/align_right.png new file mode 100644 index 000000000..899c07f1b Binary files /dev/null and b/StaticData/Icons/align_right.png differ diff --git a/StaticData/Icons/bake.png b/StaticData/Icons/bake.png new file mode 100644 index 000000000..31f9e73f3 Binary files /dev/null and b/StaticData/Icons/bake.png differ diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 3badb0ba9..515eaedcb 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 3badb0ba9d782ea89a0bb3a9f4f31daf54b8e4e7 +Subproject commit 515eaedcb719f41e4127f566b7bdf5c3c222cf6d diff --git a/Tests/MatterControl.Tests/MatterControl.Tests.csproj b/Tests/MatterControl.Tests/MatterControl.Tests.csproj index 6c0e37142..d5c4b1c71 100644 --- a/Tests/MatterControl.Tests/MatterControl.Tests.csproj +++ b/Tests/MatterControl.Tests/MatterControl.Tests.csproj @@ -116,6 +116,10 @@ {74F6BB6C-9D02-4512-A59A-21940E35C532} Gui + + {ca96058c-1a37-465d-a357-d6d695b13d25} + Localizations + {C958F745-156E-4BDC-A24A-3721C7BE7B8A} OpenGlGui diff --git a/Tests/MatterControl.Tests/SceneTests.cs b/Tests/MatterControl.Tests/SceneTests.cs index f993437a7..c4b939e14 100644 --- a/Tests/MatterControl.Tests/SceneTests.cs +++ b/Tests/MatterControl.Tests/SceneTests.cs @@ -274,10 +274,10 @@ namespace MatterHackers.PolygonMesh.UnitTests { var scene = SampleScene(); - var superGroup = scene.Descendants().Where(d => d.Name == "SuperGroup").FirstOrDefault(); - var redItem = scene.Descendants().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); - var greenItem = scene.Descendants().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); - var blueItem = scene.Descendants().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); + var superGroup = scene.DescendantsAndSelf().Where(d => d.Name == "SuperGroup").FirstOrDefault(); + var redItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); + var greenItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); + var blueItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); // Validate root Assert.AreEqual(Color.Black, scene.Color, "Color property on root should be Black"); @@ -307,10 +307,10 @@ namespace MatterHackers.PolygonMesh.UnitTests { var scene = SampleScene(); - var superGroup = scene.Descendants().Where(d => d.Name == "SuperGroup").FirstOrDefault(); - var redItem = scene.Descendants().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); - var greenItem = scene.Descendants().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); - var blueItem = scene.Descendants().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); + var superGroup = scene.DescendantsAndSelf().Where(d => d.Name == "SuperGroup").FirstOrDefault(); + var redItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); + var greenItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); + var blueItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); // Validate root Assert.AreEqual(this.RootMaterialIndex, scene.MaterialIndex, "MaterialIndex property on root should be RootMaterialIndex"); @@ -340,10 +340,10 @@ namespace MatterHackers.PolygonMesh.UnitTests { var scene = SampleScene(); - var superGroup = scene.Descendants().Where(d => d.Name == "SuperGroup").FirstOrDefault(); - var redItem = scene.Descendants().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); - var greenItem = scene.Descendants().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); - var blueItem = scene.Descendants().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); + var superGroup = scene.DescendantsAndSelf().Where(d => d.Name == "SuperGroup").FirstOrDefault(); + var redItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); + var greenItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); + var blueItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); // Validate root Assert.AreEqual(this.RootMatrix, scene.Matrix, "Matrix property on root should be RootMatrix"); @@ -373,10 +373,10 @@ namespace MatterHackers.PolygonMesh.UnitTests { var scene = SampleScene(); - var superGroup = scene.Descendants().Where(d => d.Name == "SuperGroup").FirstOrDefault(); - var redItem = scene.Descendants().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); - var greenItem = scene.Descendants().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); - var blueItem = scene.Descendants().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); + var superGroup = scene.DescendantsAndSelf().Where(d => d.Name == "SuperGroup").FirstOrDefault(); + var redItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); + var greenItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Green)).FirstOrDefault(); + var blueItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Blue)).FirstOrDefault(); // Validate root Assert.AreEqual(this.RootOutputType, scene.OutputType, "OutputType property on root should be RootOutputType"); @@ -405,7 +405,7 @@ namespace MatterHackers.PolygonMesh.UnitTests public void WorldFunctionNonExistingAncestorOverride() { var scene = SampleScene(); - var redItem = scene.Descendants().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); + var redItem = scene.DescendantsAndSelf().Where(d => d.Name == nameof(Color.Red)).FirstOrDefault(); var nonAncestor = new Object3D(); // ************************************* WorldColor ************************************* diff --git a/TextCreator/TextCreator.csproj b/TextCreator/TextCreator.csproj index d3d4b63a7..3eb4641e6 100644 --- a/TextCreator/TextCreator.csproj +++ b/TextCreator/TextCreator.csproj @@ -85,6 +85,10 @@ {036BCCBA-52D8-457C-84AE-8821F209FE4A} ImageProcessing + + {ca96058c-1a37-465d-a357-d6d695b13d25} + Localizations + {DF6845CD-64C6-4263-8357-DA8066855739} MarchingSquares