feat: ActionLeadIn uses tool window and single-contour placement
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using OpenNest.CNC.CuttingStrategy;
|
using OpenNest.CNC.CuttingStrategy;
|
||||||
using OpenNest.Controls;
|
using OpenNest.Controls;
|
||||||
using OpenNest.Converters;
|
using OpenNest.Converters;
|
||||||
|
using OpenNest.Forms;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using OpenNest.Math;
|
using OpenNest.Math;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -31,6 +32,7 @@ namespace OpenNest.Actions
|
|||||||
private SnapType activeSnapType;
|
private SnapType activeSnapType;
|
||||||
private ShapeInfo hoveredContour;
|
private ShapeInfo hoveredContour;
|
||||||
private ContextMenuStrip contextMenu;
|
private ContextMenuStrip contextMenu;
|
||||||
|
private LeadInToolWindow toolWindow;
|
||||||
private static readonly Brush grayOverlay = new SolidBrush(Color.FromArgb(160, 180, 180, 180));
|
private static readonly Brush grayOverlay = new SolidBrush(Color.FromArgb(160, 180, 180, 180));
|
||||||
private static readonly Pen highlightPen = new Pen(Color.Cyan, 2.5f);
|
private static readonly Pen highlightPen = new Pen(Color.Cyan, 2.5f);
|
||||||
|
|
||||||
@@ -46,6 +48,7 @@ namespace OpenNest.Actions
|
|||||||
plateView.MouseDown += OnMouseDown;
|
plateView.MouseDown += OnMouseDown;
|
||||||
plateView.KeyDown += OnKeyDown;
|
plateView.KeyDown += OnKeyDown;
|
||||||
plateView.Paint += OnPaint;
|
plateView.Paint += OnPaint;
|
||||||
|
ShowToolWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DisconnectEvents()
|
public override void DisconnectEvents()
|
||||||
@@ -55,6 +58,8 @@ namespace OpenNest.Actions
|
|||||||
plateView.KeyDown -= OnKeyDown;
|
plateView.KeyDown -= OnKeyDown;
|
||||||
plateView.Paint -= OnPaint;
|
plateView.Paint -= OnPaint;
|
||||||
|
|
||||||
|
HideToolWindow();
|
||||||
|
|
||||||
contextMenu?.Dispose();
|
contextMenu?.Dispose();
|
||||||
contextMenu = null;
|
contextMenu = null;
|
||||||
|
|
||||||
@@ -72,6 +77,79 @@ namespace OpenNest.Actions
|
|||||||
|
|
||||||
public override bool IsBusy() => selectedPart != null;
|
public override bool IsBusy() => selectedPart != null;
|
||||||
|
|
||||||
|
private void ShowToolWindow()
|
||||||
|
{
|
||||||
|
if (toolWindow == null)
|
||||||
|
{
|
||||||
|
toolWindow = new LeadInToolWindow();
|
||||||
|
toolWindow.AutoAssignClicked += OnAutoAssignClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load current parameters or defaults
|
||||||
|
var plate = plateView.Plate;
|
||||||
|
if (plate?.CuttingParameters != null)
|
||||||
|
toolWindow.LoadFromParameters(plate.CuttingParameters);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var json = Properties.Settings.Default.CuttingParametersJson;
|
||||||
|
if (!string.IsNullOrEmpty(json))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var saved = CuttingParametersSerializer.Deserialize(json);
|
||||||
|
toolWindow.LoadFromParameters(saved);
|
||||||
|
}
|
||||||
|
catch { /* use defaults */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toolWindow.ParametersChanged += OnToolParametersChanged;
|
||||||
|
|
||||||
|
var mainForm = plateView.FindForm();
|
||||||
|
if (mainForm != null)
|
||||||
|
toolWindow.Owner = mainForm;
|
||||||
|
|
||||||
|
toolWindow.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HideToolWindow()
|
||||||
|
{
|
||||||
|
if (toolWindow == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SaveParameters();
|
||||||
|
|
||||||
|
toolWindow.ParametersChanged -= OnToolParametersChanged;
|
||||||
|
toolWindow.AutoAssignClicked -= OnAutoAssignClicked;
|
||||||
|
toolWindow.Close();
|
||||||
|
toolWindow.Dispose();
|
||||||
|
toolWindow = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CuttingParameters GetCurrentParameters()
|
||||||
|
{
|
||||||
|
return toolWindow?.BuildParameters() ?? plateView.Plate?.CuttingParameters ?? new CuttingParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveParameters()
|
||||||
|
{
|
||||||
|
if (toolWindow == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parameters = toolWindow.BuildParameters();
|
||||||
|
var json = CuttingParametersSerializer.Serialize(parameters);
|
||||||
|
Properties.Settings.Default.CuttingParametersJson = json;
|
||||||
|
Properties.Settings.Default.Save();
|
||||||
|
|
||||||
|
if (plateView.Plate != null)
|
||||||
|
plateView.Plate.CuttingParameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnToolParametersChanged(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnMouseMove(object sender, MouseEventArgs e)
|
private void OnMouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (selectedPart == null || contours == null)
|
if (selectedPart == null || contours == null)
|
||||||
@@ -110,8 +188,14 @@ namespace OpenNest.Actions
|
|||||||
|
|
||||||
// Check endpoint/midpoint snaps on the hovered contour
|
// Check endpoint/midpoint snaps on the hovered contour
|
||||||
if (hoveredContour != null)
|
if (hoveredContour != null)
|
||||||
|
{
|
||||||
TrySnapToEntityPoints(localPt);
|
TrySnapToEntityPoints(localPt);
|
||||||
|
|
||||||
|
// Auto-switch tool window tab
|
||||||
|
if (toolWindow != null)
|
||||||
|
toolWindow.ActiveContourType = snapContourType;
|
||||||
|
}
|
||||||
|
|
||||||
plateView.Invalidate();
|
plateView.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,9 +274,7 @@ namespace OpenNest.Actions
|
|||||||
if (!hasSnap || selectedPart == null)
|
if (!hasSnap || selectedPart == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var parameters = plateView.Plate?.CuttingParameters;
|
var parameters = GetCurrentParameters();
|
||||||
if (parameters == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var leadIn = SelectLeadIn(parameters, snapContourType);
|
var leadIn = SelectLeadIn(parameters, snapContourType);
|
||||||
if (leadIn == null)
|
if (leadIn == null)
|
||||||
@@ -375,29 +457,53 @@ namespace OpenNest.Actions
|
|||||||
|
|
||||||
private void CommitLeadIn()
|
private void CommitLeadIn()
|
||||||
{
|
{
|
||||||
var parameters = plateView.Plate?.CuttingParameters;
|
var parameters = GetCurrentParameters();
|
||||||
if (parameters == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Remove any existing lead-ins first
|
|
||||||
if (selectedPart.HasManualLeadIns)
|
if (selectedPart.HasManualLeadIns)
|
||||||
selectedPart.RemoveLeadIns();
|
selectedPart.RemoveLeadIns();
|
||||||
|
|
||||||
// Apply lead-ins using the snap point as the approach point.
|
ApplyAutoTab(parameters);
|
||||||
// snapPoint is in the program's local coordinate space (rotated, not offset),
|
|
||||||
// which is what Part.ApplyLeadIns expects.
|
selectedPart.ApplySingleLeadIn(parameters, snapPoint, snapEntity, snapContourType);
|
||||||
selectedPart.ApplyLeadIns(parameters, snapPoint);
|
|
||||||
selectedPart.LeadInsLocked = true;
|
selectedPart.LeadInsLocked = true;
|
||||||
|
|
||||||
// Rebuild the layout part's graphics
|
|
||||||
selectedLayoutPart.IsDirty = true;
|
selectedLayoutPart.IsDirty = true;
|
||||||
selectedLayoutPart.Update();
|
|
||||||
|
|
||||||
// Deselect and reset
|
|
||||||
DeselectPart();
|
DeselectPart();
|
||||||
plateView.Invalidate();
|
plateView.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnAutoAssignClicked(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
if (selectedPart == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parameters = GetCurrentParameters();
|
||||||
|
|
||||||
|
if (selectedPart.HasManualLeadIns)
|
||||||
|
selectedPart.RemoveLeadIns();
|
||||||
|
|
||||||
|
ApplyAutoTab(parameters);
|
||||||
|
|
||||||
|
selectedPart.ApplyLeadIns(parameters, Vector.Zero);
|
||||||
|
selectedPart.LeadInsLocked = true;
|
||||||
|
|
||||||
|
selectedLayoutPart.IsDirty = true;
|
||||||
|
DeselectPart();
|
||||||
|
plateView.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyAutoTab(CuttingParameters parameters)
|
||||||
|
{
|
||||||
|
if (parameters.AutoTabMinSize <= 0 && parameters.AutoTabMaxSize <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bbox = selectedPart.Program.BoundingBox();
|
||||||
|
var minDim = System.Math.Min(bbox.Width, bbox.Length);
|
||||||
|
|
||||||
|
if (minDim >= parameters.AutoTabMinSize && minDim <= parameters.AutoTabMaxSize)
|
||||||
|
parameters.TabsEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void DeselectPart()
|
private void DeselectPart()
|
||||||
{
|
{
|
||||||
if (selectedLayoutPart != null)
|
if (selectedLayoutPart != null)
|
||||||
|
|||||||
Reference in New Issue
Block a user