Improving path editor
This commit is contained in:
parent
dfb5700bf8
commit
bb8d8b3859
6 changed files with 268 additions and 75 deletions
|
|
@ -75,16 +75,11 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
|
||||
private void VertexBufferChanged()
|
||||
{
|
||||
object3D.Invalidate(InvalidateType.Path);
|
||||
object3D.Invalidate(new InvalidateArgs(null, InvalidateType.Path));
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class TopAndBottomMoveXOnlyAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class XMustBeGreaterThan0Attribute : Attribute
|
||||
public class ShowAxisAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,15 +34,23 @@ using MatterHackers.Agg.UI;
|
|||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.ImageProcessing;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.VectorMath;
|
||||
using System;
|
||||
using static MatterHackers.MatterControl.PartPreviewWindow.GCode2DWidget;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public class PathEditorWidget : GuiWidget
|
||||
{
|
||||
public enum ETransformState
|
||||
{
|
||||
Edit,
|
||||
Move,
|
||||
Scale
|
||||
};
|
||||
|
||||
private Vector2 lastMousePosition = new Vector2(0, 0);
|
||||
private ETransformState mouseDownTransformOverride;
|
||||
private Vector2 mouseDownPosition = new Vector2(0, 0);
|
||||
private Action<Vector2, double> scaleChanged;
|
||||
private ThemeConfig theme;
|
||||
|
|
@ -56,7 +64,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
UndoBuffer undoBuffer,
|
||||
ThemeConfig theme,
|
||||
Action vertexChanged,
|
||||
Vector2 unscaledRenderOffset = default(Vector2),
|
||||
Vector2 unscaledRenderOffset = default,
|
||||
double layerScale = 1,
|
||||
Action<Vector2, double> scaleChanged = null)
|
||||
{
|
||||
|
|
@ -85,13 +93,76 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
var toolBar = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Bottom
|
||||
Margin = 5,
|
||||
BackgroundColor= theme.TextColor.WithAlpha(20),
|
||||
};
|
||||
|
||||
toolBar.VAnchor |= VAnchor.Bottom;
|
||||
|
||||
this.AddChild(toolBar);
|
||||
|
||||
var menuTheme = ApplicationController.Instance.MenuTheme;
|
||||
var homeButton = new ThemedTextIconButton("Home".Localize(), StaticData.Instance.LoadIcon("fa-home_16.png", 16, 16).GrayToColor(menuTheme.TextColor), theme)
|
||||
AddHomeButton(theme, toolBar);
|
||||
|
||||
toolBar.AddChild(new HorizontalSpacer());
|
||||
|
||||
AddPositionControls(theme, toolBar);
|
||||
}
|
||||
|
||||
public static readonly int VectorXYEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
|
||||
|
||||
private void AddPositionControls(ThemeConfig theme, FlowLayoutWidget toolBar)
|
||||
{
|
||||
var tabIndex = 0;
|
||||
var xEditWidget = new ThemedNumberEdit(0, theme, singleCharLabel: 'X', allowNegatives: true, allowDecimals: true, pixelWidth: VectorXYEditWidth, tabIndex: tabIndex)
|
||||
{
|
||||
TabIndex = tabIndex++,
|
||||
SelectAllOnFocus = true,
|
||||
Margin = theme.ButtonSpacing,
|
||||
VAnchor = VAnchor.Center,
|
||||
};
|
||||
xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
|
||||
{
|
||||
if (controlPointBeingDragged > -1)
|
||||
{
|
||||
var vertexData = vertexStorage[controlPointBeingDragged];
|
||||
if (vertexData.Hint == CommandHint.C4Point)
|
||||
{
|
||||
// the prev point
|
||||
if (controlPointBeingDragged > 0)
|
||||
{
|
||||
controlPointBeingDragged--;
|
||||
vertexData = new VertexData(vertexData.Command, new Vector2(vertexData.Position.X, xEditWidget.ActuallNumberEdit.Value), vertexData.Hint);
|
||||
controlPointBeingDragged++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
toolBar.AddChild(xEditWidget);
|
||||
|
||||
var yEditWidget = new ThemedNumberEdit(0, theme, 'Y', allowNegatives: true, allowDecimals: true, pixelWidth: VectorXYEditWidth, tabIndex: tabIndex)
|
||||
{
|
||||
TabIndex = tabIndex++,
|
||||
SelectAllOnFocus = true,
|
||||
VAnchor = VAnchor.Center,
|
||||
Margin = theme.ButtonSpacing,
|
||||
};
|
||||
yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
|
||||
{
|
||||
};
|
||||
yEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
|
||||
toolBar.AddChild(yEditWidget);
|
||||
}
|
||||
|
||||
private void AddHomeButton(ThemeConfig theme, FlowLayoutWidget toolBar)
|
||||
{
|
||||
var homeButton = new ThemedIconButton(StaticData.Instance.LoadIcon("fa-home_16.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
BackgroundColor = theme.SlightShade,
|
||||
HoverColor = theme.SlightShade.WithAlpha(75),
|
||||
|
|
@ -102,10 +173,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
|
||||
homeButton.Click += (s, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
ApplicationController.LaunchBrowser("https://www.matterhackers.com/store/c/3d-printer-filament");
|
||||
});
|
||||
CenterPartInView();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +183,23 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
private Affine ScalingTransform => Affine.NewScaling(layerScale, layerScale);
|
||||
private Affine TotalTransform => Affine.NewTranslation(unscaledRenderOffset) * ScalingTransform * Affine.NewTranslation(Width / 2, Height / 2);
|
||||
|
||||
private int controlPointBeingDragged = -1;
|
||||
private int controlPointBeingHovered = -1;
|
||||
|
||||
public void CenterPartInView()
|
||||
{
|
||||
if (vertexStorage != null)
|
||||
{
|
||||
var partBounds = vertexStorage.GetBounds();
|
||||
var weightedCenter = partBounds.Center;
|
||||
|
||||
unscaledRenderOffset = -weightedCenter;
|
||||
layerScale = Math.Min((Height - 30) / partBounds.Height, (Width - 30) / partBounds.Width);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDraw(Graphics2D graphics2D)
|
||||
{
|
||||
new VertexSourceApplyTransform(vertexStorage, TotalTransform).RenderCurve(graphics2D, theme.TextColor, 2, true, theme.PrimaryAccentColor.Blend(theme.TextColor, .5), theme.PrimaryAccentColor);
|
||||
|
|
@ -127,22 +212,133 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
base.OnMouseDown(mouseEvent);
|
||||
if (MouseCaptured)
|
||||
{
|
||||
controlPointBeingDragged = -1;
|
||||
|
||||
mouseDownPosition.X = mouseEvent.X;
|
||||
mouseDownPosition.Y = mouseEvent.Y;
|
||||
|
||||
lastMousePosition = mouseDownPosition;
|
||||
|
||||
mouseDownTransformOverride = TransformState;
|
||||
|
||||
// check if not left button
|
||||
switch (mouseEvent.Button)
|
||||
{
|
||||
case MouseButtons.Left:
|
||||
if (Keyboard.IsKeyDown(Keys.ControlKey))
|
||||
{
|
||||
if (Keyboard.IsKeyDown(Keys.Alt))
|
||||
{
|
||||
mouseDownTransformOverride = ETransformState.Scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseDownTransformOverride = ETransformState.Move;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are in edit mode, check if we are over any control points
|
||||
controlPointBeingDragged = GetControlPointIndex(mouseEvent.Position);
|
||||
}
|
||||
break;
|
||||
|
||||
case MouseButtons.Middle:
|
||||
mouseDownTransformOverride = ETransformState.Move;
|
||||
break;
|
||||
|
||||
case MouseButtons.Right:
|
||||
mouseDownTransformOverride = ETransformState.Scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int GetControlPointIndex(Vector2 mousePosition)
|
||||
{
|
||||
double hitThreshold = 10; // Threshold for considering a hit, in screen pixels
|
||||
|
||||
for (int i = 0; i < vertexStorage.Count; i++)
|
||||
{
|
||||
Vector2 controlPoint = vertexStorage[i].Position + unscaledRenderOffset;
|
||||
ScalingTransform.transform(ref controlPoint);
|
||||
// we center on the scren so we have to add that in after scaling
|
||||
controlPoint += new Vector2(Width / 2, Height / 2);
|
||||
|
||||
if ((controlPoint - mousePosition).Length <= hitThreshold) // Check if the mouse position is within the threshold
|
||||
{
|
||||
return i; // Control point index
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // No control point found at this position
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
base.OnMouseMove(mouseEvent);
|
||||
var mousePos = new Vector2(mouseEvent.X, mouseEvent.Y);
|
||||
|
||||
if (MouseCaptured)
|
||||
{
|
||||
DoTranslateAndZoom(mouseEvent);
|
||||
|
||||
if (controlPointBeingDragged > -1)
|
||||
{
|
||||
// we are dragging a control point
|
||||
var mouseDelta = mouseEvent.Position - lastMousePosition;
|
||||
if (mouseDelta.LengthSquared > 0)
|
||||
{
|
||||
ScalingTransform.inverse_transform(ref mouseDelta);
|
||||
OffsetSelectedPoint(mouseDelta);
|
||||
vertexChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// highlight any contorl points we are over
|
||||
}
|
||||
|
||||
lastMousePosition = mouseEvent.Position;
|
||||
}
|
||||
|
||||
private void OffsetSelectedPoint(Vector2 delta)
|
||||
{
|
||||
if (controlPointBeingDragged < 0
|
||||
|| controlPointBeingDragged >= vertexStorage.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var vertexData = vertexStorage[controlPointBeingDragged];
|
||||
|
||||
if (vertexData.Hint == CommandHint.C4Point)
|
||||
{
|
||||
for (int i = -1; i < 2; i++)
|
||||
{
|
||||
var pointIndex = controlPointBeingDragged + i;
|
||||
// the prev point
|
||||
if (pointIndex > 0
|
||||
&& pointIndex < vertexStorage.Count)
|
||||
{
|
||||
var vertexData2 = vertexStorage[pointIndex];
|
||||
vertexStorage[pointIndex] = new VertexData(vertexData2.Command, vertexData2.Position + delta, vertexData2.Hint);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// only drag the point
|
||||
vertexStorage[controlPointBeingDragged] = new VertexData(vertexData.Command, vertexData.Position + delta, vertexData.Hint);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoTranslateAndZoom(MouseEventArgs mouseEvent)
|
||||
{
|
||||
var mousePos = new Vector2(mouseEvent.X, mouseEvent.Y);
|
||||
var mouseDelta = mousePos - lastMousePosition;
|
||||
switch (TransformState)
|
||||
|
||||
switch (mouseDownTransformOverride)
|
||||
{
|
||||
case ETransformState.Scale:
|
||||
double zoomDelta = 1;
|
||||
|
|
@ -168,20 +364,20 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
break;
|
||||
|
||||
case ETransformState.Move:
|
||||
default: // also treat everything else like a move
|
||||
ScalingTransform.inverse_transform(ref mouseDelta);
|
||||
|
||||
unscaledRenderOffset += mouseDelta;
|
||||
scaleChanged?.Invoke(unscaledRenderOffset, layerScale);
|
||||
break;
|
||||
|
||||
case ETransformState.Edit:
|
||||
default: // also treat everything else like an edit
|
||||
break;
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
lastMousePosition = mousePos;
|
||||
}
|
||||
|
||||
public override void OnMouseWheel(MouseEventArgs mouseEvent)
|
||||
{
|
||||
base.OnMouseWheel(mouseEvent);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
|
|
@ -59,8 +58,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
Name = "Radial Pinch".Localize();
|
||||
}
|
||||
|
||||
[PathEditorFactory.TopAndBottomMoveXOnly]
|
||||
[PathEditorFactory.XMustBeGreaterThan0]
|
||||
[PathEditorFactory.ShowAxis]
|
||||
public PathEditorFactory.EditableVertexStorage PathForHorizontalOffsets { get; set; } = new PathEditorFactory.EditableVertexStorage();
|
||||
|
||||
[Description("Specifies the number of vertical cuts required to ensure the part can be pinched well.")]
|
||||
|
|
@ -117,14 +115,6 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
return AxisAlignedBoundingBox.CenteredBox(new Vector3(1, 1, sourceAabb.ZSize), center).NewTransformed(this.WorldMatrix());
|
||||
}
|
||||
|
||||
public Vector2 Point1 { get; set; } = new Vector2(0, 0);
|
||||
public Vector2 Point2 {get; set;} = new Vector2(1, 4);
|
||||
public Vector2 Point3 { get; set;} = new Vector2(2, 8);
|
||||
public Vector2 Point4 { get; set;} = new Vector2(3, 12);
|
||||
public Vector2 Point5 { get; set;} = new Vector2(4, 14);
|
||||
public Vector2 Point6 { get; set;} = new Vector2(5, 16);
|
||||
public Vector2 Point7 { get; set;} = new Vector2(6, 18);
|
||||
|
||||
public override Task Rebuild()
|
||||
{
|
||||
this.DebugDepth("Rebuild");
|
||||
|
|
@ -174,13 +164,22 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
|
||||
var maxRadius = enclosingCircle.Radius + RotationOffset.Length;
|
||||
|
||||
//if (PathForHorizontalOffsets.Count == 0)
|
||||
// if there is no path make a bad one
|
||||
if (PathForHorizontalOffsets.Count == 0)
|
||||
{
|
||||
var bottomPoint = new Vector2(maxRadius, bottom * 10);
|
||||
var topPoint = new Vector2(maxRadius, top * 10);
|
||||
var middlePoint = (bottomPoint + topPoint) / 2;
|
||||
middlePoint.X *= 2;
|
||||
|
||||
var Point1 = new Vector2(0, 0);
|
||||
var Point2 = new Vector2(1, 4);
|
||||
var Point3 = new Vector2(2, 8);
|
||||
var Point4 = new Vector2(3, 12);
|
||||
var Point5 = new Vector2(4, 14);
|
||||
var Point6 = new Vector2(5, 16);
|
||||
var Point7 = new Vector2(6, 18);
|
||||
|
||||
PathForHorizontalOffsets.Clear();
|
||||
PathForHorizontalOffsets.MoveTo(Point1);
|
||||
PathForHorizontalOffsets.Curve4(Point2, Point3, Point4);
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@ either expressed or implied, of the FreeBSD Project.
|
|||
*/
|
||||
|
||||
using System.Linq;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.DesignTools;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.SlicerConfiguration
|
||||
|
|
@ -82,10 +80,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
|
||||
{
|
||||
this.SetValue(
|
||||
string.Format("{0},{1}", xEditWidget.ActuallNumberEdit.Value.ToString("0.###"), yEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
string.Format("{0},{1}",
|
||||
xEditWidget.ActuallNumberEdit.Value.ToString("0.###"),
|
||||
yEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
userInitiated: true);
|
||||
};
|
||||
|
||||
xEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
|
||||
container.AddChild(xEditWidget);
|
||||
|
|
@ -101,10 +100,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
|
||||
{
|
||||
this.SetValue(
|
||||
string.Format("{0},{1}", xEditWidget.ActuallNumberEdit.Value.ToString("0.###"), yEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
string.Format("{0},{1}",
|
||||
xEditWidget.ActuallNumberEdit.Value.ToString("0.###"),
|
||||
yEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
userInitiated: true);
|
||||
};
|
||||
|
||||
yEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
|
||||
container.AddChild(yEditWidget);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
zEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
userInitiated: true);
|
||||
};
|
||||
xEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
|
||||
container.AddChild(xEditWidget);
|
||||
|
||||
|
|
@ -110,6 +111,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
zEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
userInitiated: true);
|
||||
};
|
||||
yEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
|
||||
container.AddChild(yEditWidget);
|
||||
|
||||
|
|
@ -132,6 +134,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
zEditWidget.ActuallNumberEdit.Value.ToString("0.###")),
|
||||
userInitiated: true);
|
||||
};
|
||||
zEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown;
|
||||
|
||||
container.AddChild(zEditWidget);
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4329e51c1d2a762a42176e1a1aac9bac43f02da6
|
||||
Subproject commit 3c76fcb1852d66078ab527e5871dd8c62865680b
|
||||
Loading…
Add table
Add a link
Reference in a new issue