refactor(engine): select desktop nesting through app-scoped jobs engine
Replace the MainForm/AutoNestForm engine combo bindings and every desktop NestEngineRegistry call: selection now lives in app-scoped EngineSelection addressing jobs engines in NestingEngineRegistry, the combo lists the four built-in strategies (StockLadder stays out per the frozen UI decision), and Engines/ plug-ins load through NestingEngineRegistry.LoadPlugins. Whole-job fill routes through the public PlateFillService with the selected strategy and plate number; interactive group fill (PlateView) and area fill (ActionFillArea) go through PlateFillService with identical accept/cancel preview behavior. Multi-plate and size-search orchestrators receive the explicit strategy. No desktop code reads or writes process-global engine state.
This commit is contained in:
@@ -6,6 +6,8 @@ using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using OpenNest.Controls;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
using OpenNest.Forms;
|
||||
|
||||
namespace OpenNest.Actions
|
||||
{
|
||||
@@ -46,13 +48,15 @@ namespace OpenNest.Actions
|
||||
|
||||
private async void FillArea()
|
||||
{
|
||||
var strategy = EngineSelection.FillStrategy;
|
||||
if (progress != null && cts != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var engine = NestEngineRegistry.Create(plateView.Plate);
|
||||
var parts = await Task.Run(() =>
|
||||
engine.Fill(
|
||||
PlateFillService.FillItem(
|
||||
strategy,
|
||||
plateView.Plate,
|
||||
new NestItem { Drawing = drawing },
|
||||
SelectedArea,
|
||||
progress,
|
||||
@@ -69,8 +73,15 @@ namespace OpenNest.Actions
|
||||
}
|
||||
else
|
||||
{
|
||||
var engine = NestEngineRegistry.Create(plateView.Plate);
|
||||
engine.Fill(new NestItem { Drawing = drawing }, SelectedArea);
|
||||
var parts = PlateFillService.FillItem(
|
||||
strategy,
|
||||
plateView.Plate,
|
||||
new NestItem { Drawing = drawing },
|
||||
SelectedArea,
|
||||
null,
|
||||
CancellationToken.None
|
||||
);
|
||||
plateView.Plate.Parts.AddRange(parts);
|
||||
plateView.Invalidate();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
using Timer = System.Timers.Timer;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
|
||||
namespace OpenNest.Controls
|
||||
{
|
||||
@@ -602,11 +603,18 @@ namespace OpenNest.Controls
|
||||
|
||||
try
|
||||
{
|
||||
var engine = NestEngineRegistry.Create(Plate);
|
||||
var strategy = EngineSelection.FillStrategy;
|
||||
var spacing = Plate.PartSpacing;
|
||||
var parts = await Task.Run(() =>
|
||||
{
|
||||
var result = engine.Fill(groupParts, workArea, progress, cts.Token);
|
||||
var result = PlateFillService.FillGroup(
|
||||
strategy,
|
||||
Plate,
|
||||
groupParts,
|
||||
workArea,
|
||||
progress,
|
||||
cts.Token
|
||||
);
|
||||
Compactor.Settle(result, workArea, spacing);
|
||||
return result;
|
||||
});
|
||||
|
||||
@@ -87,9 +87,9 @@ namespace OpenNest.Forms
|
||||
|
||||
private void LoadEngines()
|
||||
{
|
||||
foreach (var engine in NestEngineRegistry.AvailableEngines)
|
||||
engineComboBox.Items.Add(engine.Name);
|
||||
engineComboBox.SelectedItem = NestEngineRegistry.ActiveEngineName;
|
||||
foreach (var name in EngineSelection.UiEngineNames)
|
||||
engineComboBox.Items.Add(name);
|
||||
engineComboBox.SelectedItem = EngineSelection.EngineName;
|
||||
}
|
||||
|
||||
private void SetupPartsGrid()
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenNest.Engine.Jobs;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
|
||||
namespace OpenNest.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// App-scoped nesting-engine selection — the desktop replacement for the process-global
|
||||
/// NestEngineRegistry.ActiveEngineName. The selected name addresses a whole-job
|
||||
/// INestingEngine resolved through NestingEngineRegistry at call time; single-plate
|
||||
/// interactive fill uses FillStrategy, which maps a built-in engine to its placement
|
||||
/// strategy and falls back to Default for jobs-only engines (StockLadder, plug-ins).
|
||||
/// </summary>
|
||||
public static class EngineSelection
|
||||
{
|
||||
public const string DefaultEngineName = "Default";
|
||||
|
||||
/// <summary>Registered jobs engine deliberately kept out of the desktop combo.</summary>
|
||||
public const string HiddenEngineName = "StockLadder";
|
||||
|
||||
private static string engineName = DefaultEngineName;
|
||||
|
||||
public static string EngineName
|
||||
{
|
||||
get { return engineName; }
|
||||
set
|
||||
{
|
||||
engineName = string.IsNullOrWhiteSpace(value)
|
||||
? DefaultEngineName
|
||||
: value.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Desktop combo contents: registered jobs engines minus StockLadder.</summary>
|
||||
public static IEnumerable<string> UiEngineNames =>
|
||||
NestingEngineRegistry.AvailableEngines
|
||||
.Where(e => !e.Name.Equals(HiddenEngineName, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(e => e.Name)
|
||||
.ToList();
|
||||
|
||||
/// <summary>Placement strategy for single-plate fill: the selection when it names a
|
||||
/// built-in strategy, otherwise Default.</summary>
|
||||
public static string FillStrategy => IsFillStrategy(engineName) ? engineName : DefaultEngineName;
|
||||
|
||||
public static bool IsFillStrategy(string name) =>
|
||||
!string.IsNullOrWhiteSpace(name)
|
||||
&& PlateFillService.BuiltInStrategies.Any(
|
||||
s => s.Equals(name.Trim(), StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
}
|
||||
}
|
||||
+28
-11
@@ -17,6 +17,9 @@ using OpenNest.Gpu;
|
||||
using OpenNest.IO;
|
||||
using OpenNest.Properties;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.Jobs;
|
||||
using OpenNest.Engine.Jobs.Adapters;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
|
||||
namespace OpenNest.Forms
|
||||
{
|
||||
@@ -68,16 +71,19 @@ namespace OpenNest.Forms
|
||||
//if (GpuEvaluatorFactory.GpuAvailable)
|
||||
// BestFitCache.CreateSlideComputer = () => GpuEvaluatorFactory.CreateSlideComputer();
|
||||
|
||||
// Jobs-side plug-in discovery: INestingEngine implementations are registered per
|
||||
// assembly/type with the same per-DLL isolation as before. Binary plug-ins derived
|
||||
// from the legacy NestEngineBase no longer load here after the Phase-4 removal.
|
||||
var enginesDir = Path.Combine(Application.StartupPath, "Engines");
|
||||
NestEngineRegistry.LoadPlugins(enginesDir);
|
||||
NestingEngineRegistry.LoadPlugins(enginesDir);
|
||||
|
||||
OptionsForm.ApplyDisabledStrategies();
|
||||
ColorSchemeRegistry.ApplyActiveFromSettings();
|
||||
|
||||
foreach (var engine in NestEngineRegistry.AvailableEngines)
|
||||
engineComboBox.Items.Add(engine.Name);
|
||||
foreach (var name in EngineSelection.UiEngineNames)
|
||||
engineComboBox.Items.Add(name);
|
||||
|
||||
engineComboBox.SelectedItem = NestEngineRegistry.ActiveEngineName;
|
||||
engineComboBox.SelectedItem = EngineSelection.EngineName;
|
||||
engineComboBox.SelectedIndexChanged += EngineComboBox_SelectedIndexChanged;
|
||||
}
|
||||
|
||||
@@ -334,7 +340,7 @@ namespace OpenNest.Forms
|
||||
private void EngineComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (engineComboBox.SelectedItem is string name)
|
||||
NestEngineRegistry.ActiveEngineName = name;
|
||||
EngineSelection.EngineName = name;
|
||||
}
|
||||
|
||||
private void UpdateLocationMode()
|
||||
@@ -1009,7 +1015,7 @@ namespace OpenNest.Forms
|
||||
|
||||
if (form.EngineName != null)
|
||||
{
|
||||
NestEngineRegistry.ActiveEngineName = form.EngineName;
|
||||
EngineSelection.EngineName = form.EngineName;
|
||||
engineComboBox.SelectedItem = form.EngineName;
|
||||
}
|
||||
|
||||
@@ -1118,6 +1124,7 @@ namespace OpenNest.Forms
|
||||
SortOrder = sortOrder,
|
||||
MinRemnantSize = minRemnantSize,
|
||||
AllowPlateCreation = allowPlateCreation,
|
||||
Strategy = EngineSelection.FillStrategy,
|
||||
};
|
||||
|
||||
var result = await Task.Run(() =>
|
||||
@@ -1199,7 +1206,8 @@ namespace OpenNest.Forms
|
||||
salvageRate,
|
||||
plate,
|
||||
progress,
|
||||
token
|
||||
token,
|
||||
EngineSelection.FillStrategy
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1223,10 +1231,19 @@ namespace OpenNest.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
var engine = NestEngineRegistry.Create(plate);
|
||||
engine.PlateNumber = plateIndex;
|
||||
|
||||
nestParts = await Task.Run(() => engine.Nest(items, progress, token));
|
||||
// Same preview flow as before: fill the current plate's remaining demand with the
|
||||
// selected strategy, then commit the returned parts. App-scoped selection — the
|
||||
// process-global engine registry is never consulted.
|
||||
nestParts = await Task.Run(() =>
|
||||
PlateFillService.Nest(
|
||||
EngineSelection.FillStrategy,
|
||||
plate,
|
||||
items,
|
||||
plateIndex,
|
||||
progress,
|
||||
token
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
activeForm.PlateView.ClearPreviewParts();
|
||||
|
||||
Reference in New Issue
Block a user