Consolidate scene selection operations, revise styling
|
|
@ -300,9 +300,74 @@ namespace MatterHackers.MatterControl
|
|||
|
||||
private List<SceneSelectionOperation> registeredSceneOperations = new List<SceneSelectionOperation>()
|
||||
{
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
() => "Make Support".Localize(),
|
||||
(scene) =>
|
||||
TitleResolver = () => "Group".Localize(),
|
||||
Action = (scene) => scene.GroupSelection(),
|
||||
IsEnabled = (scene) => scene.HasSelection
|
||||
&& scene.SelectedItem is SelectionGroup
|
||||
&& scene.SelectedItem.Children.Count > 1,
|
||||
Icon = AggContext.StaticData.LoadIcon("group.png").SetPreMultiply(),
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Ungroup".Localize(),
|
||||
Action = (scene) => scene.UngroupSelection(),
|
||||
IsEnabled = (scene) => scene.HasSelection,
|
||||
Icon = AggContext.StaticData.LoadIcon("ungroup.png").SetPreMultiply(),
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Duplicate".Localize(),
|
||||
Action = (scene) => scene.DuplicateSelection(),
|
||||
IsEnabled = (scene) => scene.HasSelection,
|
||||
Icon = AggContext.StaticData.LoadIcon("duplicate.png").SetPreMultiply(),
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Remove".Localize(),
|
||||
Action = (scene) => scene.DeleteSelection(),
|
||||
IsEnabled = (scene) => scene.HasSelection,
|
||||
Icon = AggContext.StaticData.LoadIcon("remove.png").SetPreMultiply(),
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Lay Flat".Localize(),
|
||||
Action = (scene) =>
|
||||
{
|
||||
if (scene.HasSelection)
|
||||
{
|
||||
scene.MakeLowestFaceFlat(scene.SelectedItem, scene.RootItem);
|
||||
}
|
||||
},
|
||||
IsEnabled = (scene) => scene.HasSelection,
|
||||
Icon = AggContext.StaticData.LoadIcon("lay_flat.png").SetPreMultiply(),
|
||||
},
|
||||
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Subtract".Localize(),
|
||||
Action = (scene) => DoOpperation(scene, nameof(SubtractEditor), "Subtract"),
|
||||
Icon = AggContext.StaticData.LoadIcon("subtract.png").SetPreMultiply(),
|
||||
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Intersect".Localize(),
|
||||
Action = (scene) => DoOpperation(scene, nameof(IntersectionEditor), "Intersect"),
|
||||
Icon = AggContext.StaticData.LoadIcon("intersect.png")
|
||||
},
|
||||
#if DEBUG // keep this work in progress to the editor for now
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Paint Material".Localize(),
|
||||
Action = (scene) => DoOpperation(scene, nameof(PaintMaterialEditor), "Material Paint"),
|
||||
Icon = AggContext.StaticData.LoadIcon("paint.png").SetPreMultiply(),
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
TitleResolver = () => "Make Support".Localize(),
|
||||
Action = (scene) =>
|
||||
{
|
||||
if (scene.SelectedItem != null
|
||||
&& scene.SelectedItem.OutputType != PrintOutputTypes.Support)
|
||||
|
|
@ -311,31 +376,21 @@ namespace MatterHackers.MatterControl
|
|||
}
|
||||
}
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
() => "Subtract".Localize(),
|
||||
(scene) => DoOpperation(scene, nameof(SubtractEditor), "Subtract")
|
||||
TitleResolver = () => "Bend".Localize(),
|
||||
Action = (scene) => new BendOperation(scene.SelectedItem),
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
() => "Intersect".Localize(),
|
||||
(scene) => DoOpperation(scene, nameof(IntersectionEditor), "Intersect")
|
||||
},
|
||||
#if DEBUG // keep this work in progress to the editor for now
|
||||
{
|
||||
() => "Paint Material".Localize(),
|
||||
(scene) => DoOpperation(scene, nameof(PaintMaterialEditor), "Material Paint")
|
||||
},
|
||||
{
|
||||
() => "Bend".Localize(),
|
||||
(scene) => new BendOperation(scene.SelectedItem)
|
||||
},
|
||||
{
|
||||
() => "Cut Out".Localize(),
|
||||
(scene) => Console.WriteLine("Cut out")
|
||||
TitleResolver = () => "Cut Out".Localize(),
|
||||
Action = (scene) => Console.WriteLine("Cut out")
|
||||
},
|
||||
new SceneSelectionOperation()
|
||||
{
|
||||
// Should be a pinch command that makes a pinch object with the correct controls
|
||||
() => "Pinch".Localize(),
|
||||
(scene) => scene.UndoBuffer.AddAndDo(new GroupCommand(scene, scene.SelectedItem))
|
||||
TitleResolver = () => "Pinch".Localize(),
|
||||
Action = (scene) => scene.UndoBuffer.AddAndDo(new GroupCommand(scene, scene.SelectedItem))
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
|
@ -1105,10 +1160,7 @@ namespace MatterHackers.MatterControl
|
|||
return Enumerable.Empty<PrintItemAction>();
|
||||
}
|
||||
|
||||
public IEnumerable<SceneSelectionOperation> RegisteredSceneOperations()
|
||||
{
|
||||
return registeredSceneOperations;
|
||||
}
|
||||
public IEnumerable<SceneSelectionOperation> RegisteredSceneOperations => registeredSceneOperations;
|
||||
|
||||
public event EventHandler<WidgetSourceEventArgs> AddPrintersTabRightElement;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MeshVisualizer;
|
||||
|
||||
namespace MatterHackers.Agg.UI
|
||||
{
|
||||
|
|
@ -54,11 +53,13 @@ namespace MatterHackers.Agg.UI
|
|||
{
|
||||
public Func<string> TitleResolver { get; set; }
|
||||
public string Title => this.TitleResolver?.Invoke();
|
||||
public ImageBuffer Icon { get; set; }
|
||||
}
|
||||
|
||||
public class SceneSelectionOperation : LocalizedAction
|
||||
{
|
||||
public Action<InteractiveScene> Action { get; set; }
|
||||
public Func<InteractiveScene, bool> IsEnabled { get; set; }
|
||||
}
|
||||
|
||||
public static class NamedActionExtensions
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ using MatterHackers.Agg.Image;
|
|||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.ImageProcessing;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
|
||||
namespace MatterHackers.MatterControl.Library
|
||||
{
|
||||
|
|
@ -64,13 +63,20 @@ namespace MatterHackers.MatterControl.Library
|
|||
var contentProvider = ApplicationController.Instance.Library.GetContentProvider(item) as ISceneContentProvider;
|
||||
return contentProvider?.CreateItem(item, reporter);
|
||||
}
|
||||
|
||||
|
||||
// Color ExtensionMethods
|
||||
public static ImageBuffer MultiplyWithPrimaryAccent(this ImageBuffer sourceImage)
|
||||
{
|
||||
return sourceImage.Multiply(ActiveTheme.Instance.PrimaryAccentColor);
|
||||
}
|
||||
|
||||
public static ImageBuffer SetPreMultiply(this ImageBuffer sourceImage)
|
||||
{
|
||||
sourceImage.SetRecieveBlender(new BlenderPreMultBGRA());
|
||||
|
||||
return sourceImage;
|
||||
}
|
||||
|
||||
public static ImageBuffer AlphaToPrimaryAccent(this ImageBuffer sourceImage)
|
||||
{
|
||||
return sourceImage.AnyAlphaToColor(ActiveTheme.Instance.PrimaryAccentColor);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
private View3DWidget view3DWidget;
|
||||
private InteractiveScene scene;
|
||||
private PrinterConfig printer;
|
||||
private List<NamedAction> sceneActions;
|
||||
private Dictionary<Type, HashSet<IObject3DEditor>> objectEditorsByType;
|
||||
private ObservableCollection<GuiWidget> materialButtons = new ObservableCollection<GuiWidget>();
|
||||
private SectionWidget editorSection;
|
||||
|
|
@ -75,61 +74,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
this.scene = scene;
|
||||
this.printer = printer;
|
||||
|
||||
sceneActions = new List<NamedAction>
|
||||
{
|
||||
new NamedAction()
|
||||
{
|
||||
Title = "Ungroup".Localize(),
|
||||
Action = () =>
|
||||
{
|
||||
scene.UngroupSelection();
|
||||
},
|
||||
IsEnabled = () => scene.HasSelection
|
||||
},
|
||||
new NamedAction()
|
||||
{
|
||||
Title = "Group".Localize(),
|
||||
Action = () =>
|
||||
{
|
||||
scene.GroupSelection();
|
||||
},
|
||||
IsEnabled = () => scene.HasSelection
|
||||
&& scene.SelectedItem is SelectionGroup
|
||||
&& scene.SelectedItem.Children.Count > 1
|
||||
},
|
||||
|
||||
new NamedAction()
|
||||
{
|
||||
Title = "Lay Flat".Localize(),
|
||||
Action = () =>
|
||||
{
|
||||
if (scene.HasSelection)
|
||||
{
|
||||
MakeLowestFaceFlat(scene.SelectedItem, scene.RootItem);
|
||||
}
|
||||
},
|
||||
IsEnabled = () => scene.HasSelection
|
||||
},
|
||||
new NamedAction()
|
||||
{
|
||||
Title = "Duplicate".Localize(),
|
||||
Action = () =>
|
||||
{
|
||||
scene.DuplicateSelection();
|
||||
},
|
||||
IsEnabled = () => scene.HasSelection
|
||||
},
|
||||
new NamedAction()
|
||||
{
|
||||
Title = "Remove".Localize(),
|
||||
Action = () =>
|
||||
{
|
||||
scene.DeleteSelection();
|
||||
},
|
||||
IsEnabled = () => scene.HasSelection
|
||||
}
|
||||
};
|
||||
|
||||
var firstPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
Padding = 10,
|
||||
|
|
@ -218,27 +162,30 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
var operationsContainer = new FlowLeftRightWithWrapping();
|
||||
|
||||
foreach (var sceneAction in sceneActions)
|
||||
foreach (var namedAction in ApplicationController.Instance.RegisteredSceneOperations)
|
||||
{
|
||||
var button = new TextButton(sceneAction.Title, theme)
|
||||
{
|
||||
Name = sceneAction.Title + " Button",
|
||||
Margin = theme.ButtonSpacing,
|
||||
BackgroundColor = theme.MinimalShade
|
||||
};
|
||||
button.Click += (s, e) => sceneAction.Action.Invoke();
|
||||
GuiWidget button;
|
||||
|
||||
operationsContainer.AddChild(button);
|
||||
}
|
||||
|
||||
foreach (var namedAction in ApplicationController.Instance.RegisteredSceneOperations())
|
||||
{
|
||||
var button = new TextButton(namedAction.Title, theme)
|
||||
if (namedAction.Icon != null)
|
||||
{
|
||||
Name = namedAction.Title + " Button",
|
||||
Margin = theme.ButtonSpacing,
|
||||
BackgroundColor = theme.MinimalShade
|
||||
};
|
||||
button = new IconButton(namedAction.Icon, theme)
|
||||
{
|
||||
Name = namedAction.Title + " Button",
|
||||
ToolTipText = namedAction.Title,
|
||||
Margin = theme.ButtonSpacing,
|
||||
BackgroundColor = theme.MinimalShade
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
button = new TextButton(namedAction.Title, theme)
|
||||
{
|
||||
Name = namedAction.Title + " Button",
|
||||
Margin = theme.ButtonSpacing,
|
||||
BackgroundColor = theme.MinimalShade
|
||||
};
|
||||
}
|
||||
|
||||
button.Click += (s, e) =>
|
||||
{
|
||||
namedAction.Action.Invoke(scene);
|
||||
|
|
@ -492,104 +439,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
return widget;
|
||||
}
|
||||
|
||||
private void MakeLowestFaceFlat(IObject3D objectToLayFlatGroup, IObject3D root)
|
||||
{
|
||||
bool firstVertex = true;
|
||||
|
||||
IObject3D objectToLayFlat = objectToLayFlatGroup;
|
||||
|
||||
IVertex lowestVertex = null;
|
||||
Vector3 lowestVertexPosition = Vector3.Zero;
|
||||
IObject3D itemToLayFlat = null;
|
||||
|
||||
// Process each child, checking for the lowest vertex
|
||||
var objectsToCheck = objectToLayFlat.VisibleMeshes();
|
||||
foreach (var itemToCheck in objectsToCheck)
|
||||
{
|
||||
// find the lowest point on the model
|
||||
for (int testIndex = 0; testIndex < itemToCheck.Mesh.Vertices.Count; testIndex++)
|
||||
{
|
||||
var vertex = itemToCheck.Mesh.Vertices[testIndex];
|
||||
Vector3 vertexPosition = Vector3.Transform(vertex.Position, itemToCheck.WorldMatrix(root));
|
||||
if (firstVertex)
|
||||
{
|
||||
lowestVertex = itemToCheck.Mesh.Vertices[testIndex];
|
||||
lowestVertexPosition = vertexPosition;
|
||||
itemToLayFlat = itemToCheck;
|
||||
firstVertex = false;
|
||||
}
|
||||
else if (vertexPosition.Z < lowestVertexPosition.Z)
|
||||
{
|
||||
lowestVertex = itemToCheck.Mesh.Vertices[testIndex];
|
||||
lowestVertexPosition = vertexPosition;
|
||||
itemToLayFlat = itemToCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lowestVertex == null)
|
||||
{
|
||||
// didn't find any selected mesh
|
||||
return;
|
||||
}
|
||||
|
||||
Face faceToLayFlat = null;
|
||||
double lowestAngleOfAnyFace = double.MaxValue;
|
||||
// Check all the faces that are connected to the lowest point to find out which one to lay flat.
|
||||
foreach (Face face in lowestVertex.ConnectedFaces())
|
||||
{
|
||||
double biggestAngleToFaceVertex = double.MinValue;
|
||||
foreach (IVertex faceVertex in face.Vertices())
|
||||
{
|
||||
if (faceVertex != lowestVertex)
|
||||
{
|
||||
Vector3 faceVertexPosition = Vector3.Transform(faceVertex.Position, itemToLayFlat.WorldMatrix(root));
|
||||
Vector3 pointRelLowest = faceVertexPosition - lowestVertexPosition;
|
||||
double xLeg = new Vector2(pointRelLowest.X, pointRelLowest.Y).Length;
|
||||
double yLeg = pointRelLowest.Z;
|
||||
double angle = Math.Atan2(yLeg, xLeg);
|
||||
if (angle > biggestAngleToFaceVertex)
|
||||
{
|
||||
biggestAngleToFaceVertex = angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (biggestAngleToFaceVertex < lowestAngleOfAnyFace)
|
||||
{
|
||||
lowestAngleOfAnyFace = biggestAngleToFaceVertex;
|
||||
faceToLayFlat = face;
|
||||
}
|
||||
}
|
||||
|
||||
double maxDistFromLowestZ = 0;
|
||||
List<Vector3> faceVertices = new List<Vector3>();
|
||||
foreach (IVertex vertex in faceToLayFlat.Vertices())
|
||||
{
|
||||
Vector3 vertexPosition = Vector3.Transform(vertex.Position, itemToLayFlat.WorldMatrix(root));
|
||||
faceVertices.Add(vertexPosition);
|
||||
maxDistFromLowestZ = Math.Max(maxDistFromLowestZ, vertexPosition.Z - lowestVertexPosition.Z);
|
||||
}
|
||||
|
||||
if (maxDistFromLowestZ > .001)
|
||||
{
|
||||
Vector3 xPositive = (faceVertices[1] - faceVertices[0]).GetNormal();
|
||||
Vector3 yPositive = (faceVertices[2] - faceVertices[0]).GetNormal();
|
||||
Vector3 planeNormal = Vector3.Cross(xPositive, yPositive).GetNormal();
|
||||
|
||||
// this code takes the minimum rotation required and looks much better.
|
||||
Quaternion rotation = new Quaternion(planeNormal, new Vector3(0, 0, -1));
|
||||
Matrix4X4 partLevelMatrix = Matrix4X4.CreateRotation(rotation);
|
||||
|
||||
// rotate it
|
||||
objectToLayFlatGroup.Matrix = PlatingHelper.ApplyAtCenter(objectToLayFlatGroup, partLevelMatrix);
|
||||
|
||||
scene.Invalidate();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
PlatingHelper.PlaceOnBed(objectToLayFlatGroup);
|
||||
}
|
||||
|
||||
private List<TransformData> GetTransforms(int axisIndex, AxisAlignment alignment)
|
||||
{
|
||||
var transformDatas = new List<TransformData>();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ of the authors and should not be interpreted as representing official policies,
|
|||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
|
@ -34,6 +35,7 @@ using System.Threading.Tasks;
|
|||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.PartPreviewWindow
|
||||
|
|
@ -212,6 +214,102 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
}
|
||||
}
|
||||
|
||||
public static void MakeLowestFaceFlat(this InteractiveScene scene, IObject3D objectToLayFlatGroup, IObject3D root)
|
||||
{
|
||||
bool firstVertex = true;
|
||||
|
||||
IObject3D objectToLayFlat = objectToLayFlatGroup;
|
||||
|
||||
IVertex lowestVertex = null;
|
||||
Vector3 lowestVertexPosition = Vector3.Zero;
|
||||
IObject3D itemToLayFlat = null;
|
||||
|
||||
// Process each child, checking for the lowest vertex
|
||||
foreach (var itemToCheck in objectToLayFlat.VisibleMeshes())
|
||||
{
|
||||
// find the lowest point on the model
|
||||
for (int testIndex = 0; testIndex < itemToCheck.Mesh.Vertices.Count; testIndex++)
|
||||
{
|
||||
var vertex = itemToCheck.Mesh.Vertices[testIndex];
|
||||
Vector3 vertexPosition = Vector3.Transform(vertex.Position, itemToCheck.WorldMatrix(root));
|
||||
if (firstVertex)
|
||||
{
|
||||
lowestVertex = itemToCheck.Mesh.Vertices[testIndex];
|
||||
lowestVertexPosition = vertexPosition;
|
||||
itemToLayFlat = itemToCheck;
|
||||
firstVertex = false;
|
||||
}
|
||||
else if (vertexPosition.Z < lowestVertexPosition.Z)
|
||||
{
|
||||
lowestVertex = itemToCheck.Mesh.Vertices[testIndex];
|
||||
lowestVertexPosition = vertexPosition;
|
||||
itemToLayFlat = itemToCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lowestVertex == null)
|
||||
{
|
||||
// didn't find any selected mesh
|
||||
return;
|
||||
}
|
||||
|
||||
Face faceToLayFlat = null;
|
||||
double lowestAngleOfAnyFace = double.MaxValue;
|
||||
// Check all the faces that are connected to the lowest point to find out which one to lay flat.
|
||||
foreach (Face face in lowestVertex.ConnectedFaces())
|
||||
{
|
||||
double biggestAngleToFaceVertex = double.MinValue;
|
||||
foreach (IVertex faceVertex in face.Vertices())
|
||||
{
|
||||
if (faceVertex != lowestVertex)
|
||||
{
|
||||
Vector3 faceVertexPosition = Vector3.Transform(faceVertex.Position, itemToLayFlat.WorldMatrix(root));
|
||||
Vector3 pointRelLowest = faceVertexPosition - lowestVertexPosition;
|
||||
double xLeg = new Vector2(pointRelLowest.X, pointRelLowest.Y).Length;
|
||||
double yLeg = pointRelLowest.Z;
|
||||
double angle = Math.Atan2(yLeg, xLeg);
|
||||
if (angle > biggestAngleToFaceVertex)
|
||||
{
|
||||
biggestAngleToFaceVertex = angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (biggestAngleToFaceVertex < lowestAngleOfAnyFace)
|
||||
{
|
||||
lowestAngleOfAnyFace = biggestAngleToFaceVertex;
|
||||
faceToLayFlat = face;
|
||||
}
|
||||
}
|
||||
|
||||
double maxDistFromLowestZ = 0;
|
||||
List<Vector3> faceVertices = new List<Vector3>();
|
||||
foreach (IVertex vertex in faceToLayFlat.Vertices())
|
||||
{
|
||||
Vector3 vertexPosition = Vector3.Transform(vertex.Position, itemToLayFlat.WorldMatrix(root));
|
||||
faceVertices.Add(vertexPosition);
|
||||
maxDistFromLowestZ = Math.Max(maxDistFromLowestZ, vertexPosition.Z - lowestVertexPosition.Z);
|
||||
}
|
||||
|
||||
if (maxDistFromLowestZ > .001)
|
||||
{
|
||||
Vector3 xPositive = (faceVertices[1] - faceVertices[0]).GetNormal();
|
||||
Vector3 yPositive = (faceVertices[2] - faceVertices[0]).GetNormal();
|
||||
Vector3 planeNormal = Vector3.Cross(xPositive, yPositive).GetNormal();
|
||||
|
||||
// this code takes the minimum rotation required and looks much better.
|
||||
Quaternion rotation = new Quaternion(planeNormal, new Vector3(0, 0, -1));
|
||||
Matrix4X4 partLevelMatrix = Matrix4X4.CreateRotation(rotation);
|
||||
|
||||
// rotate it
|
||||
objectToLayFlatGroup.Matrix = PlatingHelper.ApplyAtCenter(objectToLayFlatGroup, partLevelMatrix);
|
||||
|
||||
scene.Invalidate();
|
||||
}
|
||||
|
||||
PlatingHelper.PlaceOnBed(objectToLayFlatGroup);
|
||||
}
|
||||
|
||||
internal class ArangeUndoCommand : IUndoRedoCommand
|
||||
{
|
||||
private List<TransformCommand> allUndoTransforms = new List<TransformCommand>();
|
||||
|
|
|
|||
BIN
StaticData/Icons/duplicate.png
Normal file
|
After Width: | Height: | Size: 927 B |
BIN
StaticData/Icons/group.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
StaticData/Icons/intersect.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
StaticData/Icons/lay_flat.png
Normal file
|
After Width: | Height: | Size: 876 B |
BIN
StaticData/Icons/paint.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
StaticData/Icons/remove.png
Normal file
|
After Width: | Height: | Size: 1,023 B |
BIN
StaticData/Icons/subtract.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
StaticData/Icons/ungroup.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |