Working on new arrange toolAdding Remove and Bake to IObject3D
Made Localize() exist in agg
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
186
DesignTools/Operations/ArrangeObject3D.cs
Normal file
|
|
@ -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<Aabb> ChildrenBounds = new List<Aabb>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
DesignTools/Operations/ArrayAdvancedObject3D.cs
Normal file
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
65
DesignTools/Operations/ArrayLinearObject3D.cs
Normal file
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Aabb> childrenBounds = new List<Aabb>();
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
90
DesignTools/Operations/ArrayRadialObject3D.cs
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<SortableAttribute>().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<SortableAttribute>().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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,9 +86,12 @@
|
|||
<Compile Include="ApplicationView\OemProfileDictionary.cs" />
|
||||
<Compile Include="ApplicationView\WindowsPlatformsFeatures.cs" />
|
||||
<Compile Include="DataStorage\ApplicationDataStorage.cs" />
|
||||
<Compile Include="DesignTools\Operations\ArangeObject3D.cs" />
|
||||
<Compile Include="DesignTools\Operations\ArrayAdvancedObject3D.cs" />
|
||||
<Compile Include="DesignTools\Operations\ArrayLinearObject3D.cs" />
|
||||
<Compile Include="DesignTools\Operations\ArrayRadialObject3D.cs" />
|
||||
<Compile Include="DesignTools\Operations\Object3DExtensions.cs" />
|
||||
<Compile Include="DesignTools\Operations\Align.cs" />
|
||||
<Compile Include="DesignTools\Operations\ArrayObject3D.cs" />
|
||||
<Compile Include="DesignTools\Operations\Scale.cs" />
|
||||
<Compile Include="DesignTools\Operations\Rotate.cs" />
|
||||
<Compile Include="DesignTools\Operations\SmoothPath.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<Type, HashSet<IObject3DEditor>> 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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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<TransformCommand> allUndoTransforms = new List<TransformCommand>();
|
||||
|
||||
public ArangeUndoCommand(View3DWidget view3DWidget, List<Matrix4X4> preArrangeTarnsforms, List<Matrix4X4> postArrangeTarnsforms)
|
||||
public ArrangeUndoCommand(View3DWidget view3DWidget, List<Matrix4X4> preArrangeTarnsforms, List<Matrix4X4> postArrangeTarnsforms)
|
||||
{
|
||||
for (int i = 0; i < preArrangeTarnsforms.Count; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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) =>
|
||||
|
|
|
|||
BIN
StaticData/Icons/align_Top.png
Normal file
|
After Width: | Height: | Size: 248 B |
BIN
StaticData/Icons/align_bottom.png
Normal file
|
After Width: | Height: | Size: 237 B |
BIN
StaticData/Icons/align_center_x.png
Normal file
|
After Width: | Height: | Size: 246 B |
BIN
StaticData/Icons/align_center_y.png
Normal file
|
After Width: | Height: | Size: 261 B |
BIN
StaticData/Icons/align_left.png
Normal file
|
After Width: | Height: | Size: 234 B |
BIN
StaticData/Icons/align_right.png
Normal file
|
After Width: | Height: | Size: 240 B |
BIN
StaticData/Icons/bake.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -1 +1 @@
|
|||
Subproject commit 3badb0ba9d782ea89a0bb3a9f4f31daf54b8e4e7
|
||||
Subproject commit 515eaedcb719f41e4127f566b7bdf5c3c222cf6d
|
||||
|
|
@ -116,6 +116,10 @@
|
|||
<Project>{74F6BB6C-9D02-4512-A59A-21940E35C532}</Project>
|
||||
<Name>Gui</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\Localizations\Localizations.csproj">
|
||||
<Project>{ca96058c-1a37-465d-a357-d6d695b13d25}</Project>
|
||||
<Name>Localizations</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\OpenGlGui\OpenGlGui.csproj">
|
||||
<Project>{C958F745-156E-4BDC-A24A-3721C7BE7B8A}</Project>
|
||||
<Name>OpenGlGui</Name>
|
||||
|
|
|
|||
|
|
@ -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 *************************************
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@
|
|||
<Project>{036BCCBA-52D8-457C-84AE-8821F209FE4A}</Project>
|
||||
<Name>ImageProcessing</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Submodules\agg-sharp\Localizations\Localizations.csproj">
|
||||
<Project>{ca96058c-1a37-465d-a357-d6d695b13d25}</Project>
|
||||
<Name>Localizations</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Submodules\agg-sharp\MarchingSquares\MarchingSquares.csproj">
|
||||
<Project>{DF6845CD-64C6-4263-8357-DA8066855739}</Project>
|
||||
<Name>MarchingSquares</Name>
|
||||
|
|
|
|||