Breaking changes
In the order they will bite an upgrading host.
1. Registration, before anything else
XFactory.Generators changes from a plain Dictionary to a ConcurrentDictionary, so parallel
Reg() calls no longer corrupt the registration map. The property is public, so a caller that
declares its type explicitly stops compiling.
Carried over from 3.1.172 and still the first thing an upgrading host hits: Reg must be called once at startup, before any project XML is deserialized. Registration no longer happens by accident when a type is first touched. See XML IO.
2. The message channel
Message reporting is rebuilt on a unified model. Every notification carries a Severity, a Category and a filterable id (SimpleMessage), and arrives on one of three typed sinks: ShellProgress for session-lifecycle messages, StepDiagnosticProgress for step-anchored diagnostics, and NcDiagnosticProgress for NC-parsing diagnostics.
MixedProgress0, MultiTagMessage and MultiTagMessageUtil are removed. Every message parameter
across the API — the XFactory deserialization chain included — is retyped
from IProgress<object> to IProgress<IMessage>. Category.General is deleted,
MessageUtil becomes id-first {Category}{Severity}, and
NcDiagnostic.Text renames to Notification. See
Message Management.
3. The session surface
LocalProjectService.SessionShell is created by BeginSession() and nulled at EndSession() — it
is null outside a session and no longer lazily created. ShellProgress
is recreated per session, so hold no long-lived reference to either: subscribe once through
OnShellMessageAdded /
OnShellMessageCleared, or buffer one call's messages
with MessageCollector.
MachiningSession takes an injected IMachiningService
host in its constructor, and IMachiningService replaces PlayerCancellationToken / PausePlayer
with a single PacePlayer property.
4. The play verbs
Nc becomes the umbrella term for any playable control program, and BrandNc names the
famous-brand controller-code group as a sibling of Cl and Csv.
| Was | Is now |
|---|---|
PlayNcFile(file) — brand G-code only |
PlayNcFile(file, NcKind kind = NcKind.Auto) |
RunNcFile(file) |
RunNcFile(file, NcKind kind = NcKind.Auto) |
| the narrow brand-only file verbs | PlayBrandNcFile / RunBrandNcFile |
IControlRunner |
Hi.Numerical.INcRunner |
RunControlLines |
RunNcLines |
ControlKind |
NcKind |
IsRunningControlLines / BeginControlRunner |
IsRunningNcLines / BeginNcRunner |
the interim PlayControlFile / RunControlFile mirrors |
removed |
The same rename applies on LocalProjectService, SessionShellController and MachiningSession.
Only .cl / .cls / .clsf / .csv arguments change meaning —
DetectByPath treats those as closed extension sets and
everything else falls back to brand G-code, so an exotic brand extension can never be misrouted.
5. Renames with no shim
| Was | Is now |
|---|---|
WorkpieceService.GetRuntimeGeom / ReadRuntimeGeom / WriteRuntimeGeom / SetRuntimeGeom / ResetRuntimeGeom / IsRuntimeGeomInit / ScanRuntimeGeomInfDefect |
GetOrBuildMeshedGeom / ReadMeshedGeom / WriteMeshedGeom / SetMeshedGeom / ResetMeshedGeom / IsMeshedGeomInit / ScanMeshedGeomInfDefect |
MachiningEquipmentCollisionIndex.WorkpieceRuntimeGeomGetter |
WorkpieceMeshedGeomGetter |
IContourTray / UniformContourTray / FreeContourTray |
IFluting / UniformFluting / FreeFluting |
MillingCutter.FluteContourTray |
Fluting |
Hi.Common.ResourceUtil (the HiNc one) |
ResourceLayout |
NativeTopoStld / NativeTopoStlfr / NativeCarveTopoStl3wfr |
NativeTopoStl3d / NativeTopoStl3wfr / CarveStl |
Solid.NativeSmoothTopoStl / Sweptable.NativeTopoStl |
SmoothTopoStl3d / NativeTopoStl3d |
ITimeGetter and its Time member |
Hi.Physics.ITimecoded and Timecode |
ClStrip.DrawingRefreshing |
ClStrip.DrawingRefreshed |
CbtrPickable.CleanLinked* |
CbtrPickable.CleanAttached* |
SoftNcRunner.NcDependencyList |
PipelineNcDependencyList |
StateActRunner.Feedrate_mmds / Feedrate_mmdmin, ActFeedrate.Feedrate_mmds / Feedrate_mmdmin (and ActRapid), MachineMotionStep.Feedrate_mmds, the MachineMotionStep constructor's feedrate_mmds parameter |
CommandedClFeedrate_mmds / CommandedClFeedrate_mmdmin, CommandedClFeedrate_mmds / CommandedClFeedrate_mmdmin, CommandedClFeedrate_mmds, commandedClFeedrate_mmds |
GetMillingEquipment |
GetMachiningEquipment |
CodeXyzabcMachineTool / CodeXyzabcMachineToolUri |
GeneralXyzabcMachineTool (the old XML names still load) |
Four notes on that table.
The SessionShell script names for meshed geometry keep hidden [Obsolete] aliases so existing
player scripts still run; the service-level members do not. WorkpieceService.ResetRuntimeGeom also
drops its ClStrip parameter.
ClStrip.DrawingRefreshed was renamed because both invocations always fired after the work — the
-ing name told subscribers the opposite of when they are called. A subscriber that misses the
rename silently detaches.
Project and cutter files written before the fluting rename keep loading: each Reg() registers the
ContourTray-era XName beside the older aliases, and the cutter element reader tries Fluting, then
FluteContourTray, then FluteContourTrackTray. A cutter that nevertheless fails to resolve its
fluting machines as a plain bounding shape rather than failing loudly, so verify the load rather than
assuming it.
The feedrate members were renamed because the value is the controller's commanded feedrate of the CL point – the F word after G94/G95/G93 conversion, or for a rapid the CL path over the act duration – and not the equipped tool's tip feedrate; under RTCP with a tool-length offset that does not describe the equipped tool the two differ. The step now also carries ActualTipFeedrate_mmds (client key ActualTipFeedrate_mmdmin), which the physics reads. The client key Feedrate_mmdmin keeps its historical name.
SoftNcRunner.PipelineNcDependencyList is the raw list; machine-config consumers read the resolved
view through GetEffectiveNcDependencyList. Legacy
<NcDependencyList> XML still loads and migrates.
6. Removals
- CSV —
CsvRunner0,LocalProjectService.EnableSoftCsvRunner, and the earlierRawCsvRunnerandCsvRowSemantic. CSV playback has one path, GeneralCsvRunner, and CsvRunner returns the CSV suit's SoftNcRunner directly. - Carriers —
IndexedSentence(wrap a bareSentencein your own ISentenceCarrier if you passed one as asourceCommand),SimpleSessionCommand, HiCbtr's[Obsolete] LsStl. The packedMixedIndexfile-line key is replaced by typed FileLineIndex comparison, so file and line positions compare by type rather than through a packed integer. - GUI-layer composition —
MachiningProjectDisplayee,IsoCoordinateEntryDisplayee,HeidenhainCoordinateEntryDisplayee,UserConfig,UserService,PlayerDivConfig. Construct LocalProjectService with theILogger-only constructor and copy the displayees from any app project —Hi.Sample.Wpf/Disp/ships them. They compose only public API (IDisplayee overLocalProjectService), so tailoring them is the point. - Managed physics kernel types — the class
FluteZData,MillingForceUtil.RuntimePack/LayerPack/AnglePack, theLayerMillingEngagementconstructor that built an engagement from a z-to-dz list (the default andBinaryReaderconstructors stay), andMillingPhysicsBrief.YieldStressMinHeight_mm. - Culture declaration —
CultureUtil.SupportedCultureNamesandCultureUtil.SetCurrentCulture(string), deleted outright with no[Obsolete]shim. What remains is English and SetCurrentCultureEn. A host that enumerated supported cultures must enumerate its own manual or resource folders instead. - Dead P/Invoke declarations — eight
gl*methods on HiDisp's publicGLclass (glFenceSync,glGetDoublev,glGetDoublei_v,glGetDoubleIndexedvEXT,glIglooInterfaceSGIX,glPNTrianglesfATI,glPNTrianglesiATI, and the already-commentedglDebugMessageCallbackAMD). They had no backing export and threwEntryPointNotFoundExceptionwhen called. NcFileListCommand— a list of NC files is just a List of Program File commands, so the dedicated type is gone. Loading a project that contains one converts it in place: each<File>entry becomes a single-file NcFileCommand (kindAuto, the same per-file extension dispatch) inside a ListCommand, and re-saving persists the converted form.- Post-Execution meshed-geometry output —
PostExecutionCommandlosesEnableWriteMeshedGeomandMeshedGeomFileTemplate(and their pre-rename…RuntimeGeom…spellings) together with theenable-write-meshed-geomandmeshed-geom-file-pathroutes. A geometry snapshot can be taken at any time-spot, unlike the run-derived outputs that command manages, so the carriers are now the placeable RecordMeshedGeomCommand and ExportMeshedGeomToStlCommand. Loading an old project with the pair enabled emitsPostExecution--MeshedGeomOutputRetired, and re-saving drops the elements. - Cutter tessellation resolution — mesh resolution is runtime data, not authored cutter data, so
the seam that let a live object be “the resolution” is gone:
MillingCutterno longer implementsIPolarResolution2dand losesLinearResolution_mm/AngleResolution_rad/AngleResolution_degandUpperBeamPolarResolution2dSource; theFunc-basedIPolarResolution2dSourcePropertyinterface is deleted together with thePolarResolution2dSourceproperties onSolid,AptProfileandCustomSpinningProfile. A Solid now holds the immutable resolution it was built with — pass it to theSolid(IGetStl, PolarResolution2d)constructor — and changing resolution means building a new solid: play paths go through SetShaperStlResolution and SetStrutStlResolution (the runner calls both for you, so the strut/upper-beam mesh follows the runtime value during a play too), holders re-mesh when you assign theirPolarResolution2dproperty, and a fresh cutter's shaper solid is born with DefaultShaperStlResolution while the strut solid is born on the geometry's own default. Cutter files keep loading whether or not they carry the old<LinearResolution_mm>/<AngleResolution_deg>elements; the values in them were only ever the residue of the last play and are ignored, and 3.2 no longer writes them — a 3.1 install needs a support-line build carrying the guarded cutter reader (HiMech 3.1.157.2 / HiNc 3.1.175.5, shipped 2026-08-29) to open a 3.2-saved cutter file. - Parameterless profile meshing —
IShaperProfileno longer extendsIGetStl, and theGetStl()convenience methods onAptProfile,ConstRatioProfile,FluteDependentRatioProfileandCustomSpinningProfileare gone. Profile mesh access is resolution-explicit: pass your value throughGenStl(resolution), or state the profile's own default withGenStl(null). Geometry types that serialize as an STL source (Cylindroid,GeomCombination,TransformationGeom,ExtendedCylinder) keepGetStl()as theirIGetStlcontract; it is documented as, and equivalent to,GenStl(null). - Bounds queries never mesh — expanding a bounding box is a rough, quick operation (view
fitting), so it no longer triggers STL generation anywhere.
TransformationGeom.ExpandToBox3dtransforms the geometry's own box corner-wise — a conservative superset of the transformed geometry's true bounds — instead of meshing, andGeomCombinationnow implementsIExpandToBox3dby folding its sources' boxes. A geometry withoutIExpandToBox3dsupport contributes nothing to a bounds query; generate the mesh yourself if you need its true extent.MillingCutter's cutter-height bookkeeping likewise reads the profile's ZR contour and the upper beam's box instead of meshing both on every cache clear. - The web application's Legacy-Controller page —
HiNC-2025-webserviceremoves the page the Page menu's third group opened, at/controller/<tab>, on 2026-09-11 (the 3.2 line). It edited HardNcEnv — the project's NcEnv, the HardNc controller model that is deprecating now that EnableSoftNcRunner defaults totrue. Controller settings are edited on the General Setup page's Controller branch (/general-setup?tree=equipment/controller), the SoftNc runner's own face — see Controller. Of the settings only that page could edit, three were HardNcEnv's alone and retire with it:EnableShortestRotary(the runner honours the program's own M126 / M127 modal codes),MaxRotarySpeedABC(the runner's rotary ceiling is the rotary rate on the branch's Rapid Feedrates leaf) andHeidenhainMasterAxisChar(a HardNc parser setting with no SoftNc counterpart). The fourth, Align P0 — moving the part so that program zero lands on a work-coordinate row — is not offered on the runner path: the Work Coordinates leaf carries only P0 and M0, which write the row from the machine position; the part is placed by hand instead — see Program Zero Alignment. Old links keep working:/controllerand anything below it redirects to the Controller branch. Nothing on the C# side moves —MachiningProject.NcEnvstill loads and the/api/Controller/*endpoints stay mounted, so a host that drives HardNcEnv through the API or a script is unaffected.
7. Signature and shape changes
- MachiningToolHouse derives from
Dictionary<int, IMachiningTool>: SetToolId takes anintand CreateStickMillingTool returnsKeyValuePair<int, MillingTool>. Any(int)entry.Keycast stops compiling. SiemensT="name"string tool calls are unaffected — they still resolve to anintat the semantic layer. - ActualTimecode and
ActualDateTime become get-only views onto the new optional
ActualTime (StepActualTime) — their
setters are gone.
AccumulatedTimeis superseded by EndTimecode, kept as an[Obsolete]alias; step CSVs write the new header and still read the old. - PreSettingCommand becomes a legacy bundle. A saved bundle expands on load
into MachiningResolutionCommand,
MachiningMotionResolutionCommand,
CollisionDetectionCommand,
PauseOnFailureCommand and PhysicsCommand (plus a
Read-mode
RecordMeshedGeomCommand), and is never written back. Anything that located the bundle element in a saved.hincprojmust look for the split commands. ToPresentDtowire keys change with the obfuscation fix: geometry DTOs useType/Min/Max/PairZrs/Z/R/SourceFile/FileIndex/LineIndex(Vec3dkeeps lowercasex/y/z), transformer DTOs useTrans,Angle_deg,CosTheta/SinTheta,Axis,Pivot,Scale,Rotation,Translation,Step,Stack,Matrix. A front-end reading those payloads must be updated in lockstep.- defaultFontFile changes value from
"Font/WCL06.ttf"to"(embedded)". It is a publicconst, so an assembly compiled against 3.1.175 already carries the old literal and keeps passing it —Initstill accepts it — but a rebuild changes what it passes, and no font file is extracted to the working directory any more. - The equipment splits into two faces. SetupEquipment is the authored one — the only face a project file persists, reached as SetupEquipment. MachiningEquipment is the runtime face the runner, physics, collision and execution display read; it is rebuilt from the authored face at project assignment and at session boundaries, so a value written onto it is discarded rather than saved. See Getting started.
8. Defaults and gates that changed
- EnableSoftNcRunner defaults to
true. The SoftNc pipeline is the NC engine; HardNcRunner is the opt-out fallback for the shrinking set of features still bound to it. - EnableNativeMillingPhysics defaults to
true, and in a shipping build setting it tofalsethrowsInvalidOperationExceptionat the setter — the managed reference implementation lives only in a non-shipping assembly. Code that flipped it off for an A/B comparison now fails at configuration time. - YieldingStressRatio and
YieldingStressRatio report
NaNinstead of0when no beam section qualifies. A caller treating0as “no yielding constraint” — as both feed solvers did — must add aNaNbranch or it will passNaNinto downstream queries. - New licence feature
NcComposition(id 22). Registering any non-built-in processing unit into a SoftNcRunner pipeline, or executing an NC-embedded C# script, requires it. Degradation is silent and functional: external units are skipped for the session with oneComposition--NotLicensednaming them, an external segmenter falls back toSingleLineSegmenter, and scripts are skipped withScript--NotLicensed. An unlicensed installation therefore produces a different simulation, not an error. Calling the public API from your own application or session script needs no extra licence; composing the interpretation pipeline does. See NC Parsing Engine. - RadiusOffsetBasis decides what a tool-house refresh writes into the D column: CutterRadius (default — geometry plus wear, the only behaviour before the basis existed) or ZeroBased (wear only, for a tool-centre CAM path). An older project refreshes exactly as before until the basis is changed. See Tool Offsets.
- The four
SnapshotSyntaxentries in the Fanuc preset default toIsEnabled = false, so projects stop serializing enabled debug snapshots. A project saved by an earlier build keeps what it serialized until its pipeline list is refreshed from the current preset. - Server side: HiNcServer pins request localization to English, so an
Accept-Language: zh-Hantrequest falls back toen. HiNcRcl removes theHiNC:DisplayEngine:FontFileconfiguration key, which never had any effect — delete it fromappsettings. FontFile remains for a custom font. - Localization: HiMech's
MachiningStep.zh-Hant/.zh-Hansresx are deleted. Step presentation strings now come from the HiNc-Resource present catalog (catalog.en.json,catalog.zh-Hant.json,catalog.zh-Hans.json) that a host overlays; a host that ships neither loses the localized step labels it used to get for free. - Packaging is x64-only: HiDisp drops the
win-x86runtime identifier and its Sentinel payload, HiNc-Resource drops the x86 platform. - The shipped machine-tool packages are renamed. They now carry the
.defaultmarker and neutral names:MachineTool/Table-B1.defaultandMachineTool/CT-350.default. The table-type package was renamed outright — its.mt, its.general-mechand its STL headers travel with it — and the duplicated nested STL set inside the CT-350 package is deleted. A project, script or.mtthat refers to a shipped machine-tool package by its earlier path must be repointed at the name above. - The shipped mechanism file takes the canonical extension.
MachineTool/Table-B1.default/Table-B1.general-mechis nowTable-B1.GeneralMechanism— the spellingGeneralMechanism.XNamegives and every Save As has written since the type-name extensions arrived — and the package'sTable-B1.mtis repointed at it..general-mechstays readable everywhere: the loader dispatches on the XML root element and never reads the extension, so a hand-authored file keeps its name and loads as before. Only something that refers to the shipped mechanism by its old file name must be repointed. The rename ships from HiNc-Resource 3.2.21; 3.2.20 still carries.general-mech, and an admin folder already seeded by it is re-mirrored — old name deleted, new name copied,Table-B1.mtrefreshed — on the first start with the newer package.