Metamation Developer Notes

  • Developer Notes
  • Resource Map
  • Tools
    • Code Formatting
    • Configuring Git
    • Assignments
    • Testing with Windows Sandbox
    • Single Binary Applications
    • Self-Updating Applications
  • Flux Workflow
    • Flux Workflow
    • Flux Development Style Guide
    • Release notes for Flux
    • SonarCloud analysis for Flux
    • Build a Flux SDK Program
    • Shipping Flux
    • Flux.Test
      • BasicBendAuto Test
      • LaserAuto.cs Detailed Documentation
      • Laserexample:Test1
  • Technical Notes
    • File formats
      • .FX File Format
      • Au(Gold) streams
      • .GEO File Format
      • .LST File Format
      • .LST file - technology
      • .BNC File Format
      • .WAD Files: Flux Resource Packages
      • .Curl Files: ASCII config information
    • Folders App
      • Data\Bendtools
      • Data\Machines
    • FluxCode
      • Welcome & Repo Map
      • Architecture & System Context
      • Subsystem *Bend* (Press Brake)
      • Subsystem *BCell* (Bend Cell Automation)
      • API Maps
      • Data Model Catalog
      • Design Patterns -- A Reader's Guide
      • Tests and Golden Paths
      • Guided Code Tours
      • CAM Glossary with Code Mapping
      • Assignments
      • Flux Onboarding Handbook
    • Data flow
      • Part
        • Part.Dwg
        • Part.Load
        • Part.Load to Part.Dwg
      • BendTech.cs
      • Bend Technology
      • Laser Cutting Technology
    • LTS (Long term support mechanism)
    • Machine ID Scheme
  • FluxTester
    • Commands and Scripts
    • Command Cookbook
    • Script Commands
    • BendTooling.cs Test Inventory
    • LaserTooling.cs Test Steps
    • Fluxtester Recipe Book
    • Nesting.cs Overview
    • Nesting.cs Recipe Book
    • Job.cs Overview
    • Job.cs Recipe Book
  • Software license
  • 3d party software
    • Python
  • Documentation
    • Bento documentation
      • Structure of a Bento page
      • Attributes
    • Software
      • Software Requirement
      • Installation
      • Git workflow for documentation contributors
    • Quick start guide
    • Workflow
      • Roles and responsibilities
      • Analyze
      • Edit
      • Proofread
      • Pre-Publish
      • Publish
      • Release cycle
      • Information required for Documentation Team
      • Checklist for Documenters
    • Styleguide
    • Flavoring
    • Translation
      • Ordering translation for a new document
    • Citations
    • Annotation
Technical Notes
/
FluxCode
/
Architecture & System Context

Architecture & System Context

Prerequisite: Chapter 00 read (repo map, eight projects, the M/V/Glob terminology). Goal: by the end you can sketch Flux’s runtime architecture on a whiteboard, name the major cross-cutting subsystems (settings, rendering, undo, persistence, hub), and explain why certain design choices were made. Reading time: 60—​90 minutes.


1. The big picture in three diagrams

1.1 Static module dependencies

                        ┌───────────────────────────────────┐
                        │           Flux.exe                │
                        │  (entry point — Flux.App)         │
                        └─────────┬─────────────────────────┘
                                  │
                                  ▼
                        ┌───────────────────────────────────┐
                        │           Flux.UI                 │
                        │  Globs (controllers) + WPF        │
                        └─────────┬─────────────────────────┘
                                  │
                                  ▼
              ┌───────────────────────────────────┐    ┌───────────┐
              │           Flux.Core               │◄───┤ Flux.API  │
              │  Models + VModels + domain logic  │    │ (3rd-party│
              └─────────┬─────────────────────────┘    │  facade)  │
                        │                              └───────────┘
                        ▼
              ┌───────────────────────────────────┐
              │          Flux.Base                │
              │  Geo, Mesh, Pline, Lux (render),  │
              │  Undo, IO primitives, FText       │
              └─────────┬─────────────────────────┘
                        │
                        ▼
              ┌───────────────────────────────────┐
              │     Flux.Hula64.dll (C++/CLI)     │
              │     wraps HOOPS for 3D import     │
              └───────────────────────────────────┘

Side projects (bind to Core):
  Flux.Test ─► Core      Flux.Migrate ─► Core      Flux.Console ─► Core

1.2 Runtime layers (a single Flux process)

┌───────────────────────────────────────────────────────────────────┐
│ Process: Flux.exe                                                 │
│  ┌──────────────────────────────────────────────────────────┐     │
│  │ Main window (App)                                        │     │
│  │   Tabs ─ each tab hosts one open Part                    │     │
│  │   Selection state, Undo stack, Glob panel                │     │
│  └────────────┬─────────────────────────────────────────────┘     │
│               │                                                   │
│               ▼                                                   │
│  ┌──────────────────────────────────────────────────────────┐     │
│  │ Open Parts (Part.Active : List<Part>)                    │     │
│  │   Part.Current ─ the active one                          │     │
│  │   each Part has Dwg / Model / BendTech / FoldTech / ...  │     │
│  └────────────┬─────────────────────────────────────────────┘     │
│               │                                                   │
│               ▼                                                   │
│  ┌──────────────────────────────────────────────────────────┐     │
│  │ Cross-cutting services (singletons / static gateways)    │     │
│  │   Hub        — global glue / dependency injection         │     │
│  │   Sheaf      — cascaded settings (per-machine, per-tech)  │     │
│  │   FX.Notes   — persistent user notes (recent items)       │     │
│  │   Lux        — rendering pipeline (OpenGL)                │     │
│  │   Lib        — wad-resource loader                        │     │
│  │   Trek       — out-of-process MetaCAM bridge              │     │
│  └──────────────────────────────────────────────────────────┘     │
└───────────────────────────────────────────────────────────────────┘
                          │
                          ▼ (file I/O, no network in Flux core)
                X:\Data, X:\Wad, X:\Resources, user data folder

1.3 Pipeline for a typical CAM job

   user opens 3D file ─►  IO (DXFReader / GeoReader / HoopsReader-via-Hula+HOOPS)
                                      │
                                      ▼
                         Part.Model (B-Rep / mesh / E3 entities)
                                      │
                       ┌──────────────┼──────────────┐
                       ▼              ▼              ▼
                 BendTech        FlatTech       FoldTech
                 (press brake)   (laser/punch)  (panel bender)
                       │              │              │
                       ▼              ▼              ▼
                 BendTooler     LaserAuto/     FoldAuto
                 (auto-tool)    AutoRouter     (sequencing)
                       │              │              │
                       └──────────────┼──────────────┘
                                      ▼
                               Postprocessor
                       (C# writer in Src\API\Bend\Post\,
                       picked by post name from BMachine.Post)
                                      │
                                      ▼
                                NC code file

2. The five layers explained

2.1 Flux.Base — foundations

Flux.Base is the CAD/CAM-agnostic foundation. It contains:

Folder What

Geo\

Point/Vector/Matrix, Pline (polyline), Profile, Spline, GeomSort, basic geometry algorithms. Geo.cs is 64 KB of constants/utilities (Geo.PI, Geo.HalfPI, Geo.QuarterPI, …​).

Mesh\

3D triangle mesh primitives (Mesh3 and friends)

Pline\

Polyline-specific helpers

Lux\

The OpenGL rendering layer — Lux, LuxDraw, LuxPanel, Scene, VModel, SGNode. Every render path goes through here.

Gold\

Au/Gold binary serialization runtime

Types\

Shared value types and enums

Undo\

Undo/redo infrastructure

IO\

Low-level IO primitives (streams, encoding)

FText\

Rich text / FTex text rendering

GL\

Lower-level OpenGL bindings

3D\

Generic 3D math beyond Geo

Rule of thumb: if a class lives in Flux.Base, it should have no awareness of bending, laser cutting, or any CAM concept. If you find such leakage, that’s a smell.

2.2 Flux.Core — the CAM engine

This is where the domain logic lives. The folder structure (16 folders) was listed in chapter 00 §4. Key points:

  • Models and VModels live together. BendOp (model) and BendOpVM (view) sit next to each other. This is not an accident — see §3 below.

  • Part (Src\Core\Part\Part.cs) is the central job aggregate, holding Model, Dwg, BendTech, FoldTech, CutTech, machine references, etc.

  • Sheaf (Src\Core\Settings\Sheaf.cs) is a cascaded settings dictionary: every domain object that has settings implements ISheafSite (string SHName, dictionary, parent fallback).

  • Hub (Src\Core\Hub.cs) is the central dependency-injection point. It exposes static Func<>/Action<> slots (e.g. BigChooser, ClosePartByJobID, APIWrapper) that are filled in at startup by the App or API layer. This is the replacement for the old "Hub whiteboard" hack and is now the official cross-layer wiring mechanism.

2.3 Flux.UI — the controllers

Flux.UI provides:

  • Globs — see §3.

  • WPF dialogs and editors — TurretEditor, SheafEditor, LaserDBEditor, MachineEditor, etc.

  • Agents — input handlers per domain (BendAgent, LaserAgent).

  • Sheets — list/grid views (BendSheet).

Convention: a domain’s UI files match the Src\UI\<domain>\<Domain>*UI.cs pattern. Files in this layer can reference Core freely; the reverse (Core → UI) is forbidden by the module dependency.

2.4 Flux.App — the shell

This is the top of the stack and the actual Flux.exe content. Responsibilities:

  • Main window, tabs, status bar.

  • Selection state, undo lifecycle, glob panel.

  • Document lifecycle (open/save/close Part).

  • Loading the right Flux.flavor and feature bits at startup.

  • Wiring up Hub slots so Core/UI can call into App services.

2.5 Flux.API — the controlled exposure

Flux.API is a narrow facade for 3rd-party automation. It:

  • Mirrors a sub-set of Core types behind API-level wrappers.

  • Bundles its dependencies (Core, Base, Hula) so consumers see only Flux.API.dll.

  • Has its own folder structure (Src\API\Job\, Src\API\Cut\, Src\API\Part\, …​) mirroring Core.

If you’re ever asked "can a 3rd party do X?", the answer is in Src\API\ — not in Core.


3. Why model and view live together

This is the most non-obvious decision in Flux’s architecture, and it is intentional. The full rationale is in Notes\Dev\1002.BuildingFlux.ftx lines 31—​61. Short version:

  • Flux objects are CAD/CAM objects tightly coupled to their visual representation. An E3Plane is meaningless without a way to render it.

  • The earlier architecture put VMs in a separate higher layer ("UI layer renders, Core only knows data"). This forced ugly workarounds for any operation that needed rendering — every setup-sheet generation, every thumbnail in an FX file, every PDF report. The result was the "Hub whiteboard": a global object bag used to fake the missing dependency.

  • The trade-off was reversed. Today, models and VMs sit in the same DLL (Flux.Core), and the rendering layer (Lux) is in Flux.Base so both can see it. Globs (controllers) remain separate in Flux.UI, because they really do need WPF/keyboard/mouse and shouldn’t be dragged into headless usage (Engine flavor, batch jobs).

Practical consequence: when adding a feature, expect to touch model + VModel + Glob. When debugging a rendering issue, you’ll be in Flux.Core, not Flux.UI. When debugging an interaction issue (mouse, keyboard, properties panel), you’ll be in Flux.UI.


4. The Glob system — controllers in detail

A Glob is a controller object that:

  1. Wraps a domain object (new BendOpGlob (op)).

  2. Exposes properties via GElement (abstract) → PanelMaker translates to WPF.

  3. Exposes commands (e.g. BendOpGlob.AddRegrip in Src\UI\Bend\BendOpUI.cs line 22).

  4. Supports composites — when multiple objects are selected, the system constructs a composite glob showing only the shared properties, and operations apply to all wrapped objects.

A glob is decorated with attributes like:

[Glob (Draw = true, Mouse = EMouse.LDown)]
public class BendOpGlob : Glob {
   public BendOpGlob (BendOp op) : base (op) { ... }
}

Draw = true means the glob has its own drawing behavior; Mouse = EMouse.LDown lets it consume mouse events. The full attribute model is in Src\UI\Glob.cs.


5. The Sheaf — cascaded settings everywhere

Every domain object that has settings implements ISheafSite:

public interface ISheafSite {
   string SHName { get; }                       // e.g. "Machine 135" or "Bend 3"
   Dictionary<SH, object> SHDict { get; set; }  // local settings (may be null)
   ISheafSite SHParent { get; }                 // fallback site
}

Reading a setting walks SHDict → SHParent.SHDict → …​ until found. This means:

  • Machine-level defaults are inherited by all bend techs that target the machine.

  • Per-tech overrides mask machine defaults.

  • Per-op overrides mask per-tech.

BendOp, BendTech, BendMachine, Part, and many others all implement ISheafSite. The keys are values of the SH enum (a domain-wide closed set of setting identifiers).

Why this matters when reading code: you’ll often see Settings.RamVBend, Settings.BGTransition, etc. accessed on a BendOp. These are resolved through the sheaf cascade — the value may have been set on the parent machine, not the op itself.


6. The Hub — wiring layers without circular dependencies

Src\Core\Hub.cs defines a static class with public delegate slots:

public static Func<string, string, IList<string>, int, bool, object, int> BigChooser;
public static Action CloseBlankMainWindow;
public static Func<string, bool, int> ClosePartByJobID;
// ... and many more

At startup, Flux.App (and optionally Flux.API) fills in these slots with concrete implementations. Core and UI then invoke them. This is dependency injection done the simple way — no DI container.

The pattern matters because:

  • It lets Core call back into App without a project reference cycle.

  • It cleanly handles the headless case (Engine flavor): Hub.BigChooser is simply null, and Core falls back to a default.

When you see Hub.ClosePartByJobID?.Invoke (...) somewhere in Core, that’s the pattern in action.


7. Rendering — the Lux pipeline

All drawing flows through Src\Base\Lux\:

File Role

Lux.cs

Static entry point — Lux.DrawMesh, Lux.Layer, Lux.Mood, etc.

LuxDraw.cs

Lower-level draw primitives.

LuxPanel.cs

The hosting WPF panel.

Scene.cs

The scene graph, manages live VModels.

VModel.cs

Base class for view-models.

SGNode

Scene-graph node — geometry, transform, or mood override.

The lifecycle of a VModel

  1. Construction. A VModel wraps a domain object (new BendMountVM (mount)).

  2. Plug into a screen. When the part is opened in a tab, the screen visits the model and calls VModel.Draw(). At first draw, the VM gets a unique Id and SGNodes are created.

  3. Live state. While Id != 0, the VM is "live" — re-renders go through cached scene-graph nodes. State changes set Dirty flags and trigger Lux.Redraw.

  4. Detach. When the part closes, scene-graph resources are released.

Layers (ELayer.BendMount, ELayer.LaserCut, …​) and moods (EMood.Selected, EMood.Normal) provide global filtering and styling.

Why this matters for debugging

If a bend setup looks wrong on screen, the bug is never in WPF — it’s in the corresponding *VM.Draw(). Set a breakpoint there, and inspect what Lux.DrawMesh is asked to render.


8. Persistence model

Format Used for Where

Curl

Machine definitions, tool catalogs, settings

Notes\Tech\2007.CurlFiles.ftx

Au / Gold

Compact binary for Part, BendTech, etc.

Notes\Dev\1003.AuGoldEncoding.ftx

FX

Native Flux file (zipped Curl/Au + thumbnail)

mentioned in 1002

DXF / DWG

2D drawing exchange

Src\Core\IO\DXFReader.cs (57 KB), DXFWriter.cs

GEO

Trumpf geometry exchange

Src\Core\IO\GeoReader.cs (33 KB), GeoWriter.cs

HOOPS-driven 3D

CATIA / Parasolid / ACIS / Pro-E / STEP via HOOPS

Src\Core\IO\HXReader.cs (39 KB — hosts HoopsReader; the filename is misleading, this is not a Hex reader)

STL

Mesh exchange

Src\Core\IO\STLModel.cs

BMC

Trumpf machine format

Src\Core\Bend\Ops\ImportBMC.cs (43 KB) — see Note 2016

DLD

Trumpf NC format

Src\Core\Bend\Ops\DLDExporter.cs

[PostLoad] — the migration hook

Au-deserialized objects can declare a [PostLoad] method that runs after deserialization. It is the standard place to migrate older versions of the same object (AuType.ObjVersion tells you which version came in). Example from BendSetup.cs:

[PostLoad]
void PostLoad () {
   mMounts.RemoveIf (a => a.Tool == null);
   mMounts.Changed += MountsChanged;
   if (mClampPos != null && AuType.ObjVersion < 4 && BMachine != null) {
      // forward-migrate older clamp positions
   }
}

When you bump a domain class in a way that changes the on-disk shape, you almost certainly need a [PostLoad] migration.


9. Threading model

Flux is predominantly single-threaded UI + opportunistic worker threads. The common patterns:

  • UI thread. Owns the main window, all WPF, all Lux rendering. The vast majority of domain code runs here.

  • Worker tasks. Long operations (auto-tooler, full simulation, large imports) may be Task.Run'd, but their results must be marshalled back to the UI thread before mutating live state.

  • Static state. Part.Current, Part.Active, BendMachine.Default, and the Hub slots are static. Treat them as UI-thread-only unless documented otherwise.

  • Cancellation. Long-running operations check Part.Flags & Part.EFlags.AbortTooling (see BendTooler.DoTooling) — there is no CancellationToken plumbing throughout.

Practical rule: do not introduce Task.Run lightly. Most "concurrency bugs" in Flux are actually re-entrancy bugs (two property setters racing on the same domain object during user interaction).


10. Undo / redo

Src\Base\Undo\ provides the undo infrastructure:

  • Each user-visible mutation is wrapped in an undo unit.

  • Globs are the canonical place to register undos (the controller knows the user intent).

  • A part’s undo stack is part-scoped — switching tabs switches stacks.

When you see code like BA.Set (ref field, value), the BA (an internal helper) is also responsible for change notification and undo bookkeeping. It is _not a plain field assignment.


11. Errors, logging, and "FX"

A small but pervasive utility class is FX (in Flux.Base). It wraps:

  • FX.Out (EOut.Info, msgId, args) — log output with a numeric message ID.

  • FX.Notes — a persistent settings store (key-value, used for "recent X").

  • FX.Testing — a global flag set when running under Flit.

  • FX.LoadTestPart, FX.TestFile, FX.TmpTestFile — test helpers.

  • FX.CopyFields — reflection-based shallow-copy helper used in shallow-copy constructors.

Two recurring exception types:

  • CodingError — internal invariant violation. Should never fire in production. Carries a numeric ID for grep-ability.

  • EResult — a result enum used by methods that can fail (EResult.OK, plus various failure modes). Preferred over throwing for predictable failure paths.

Notes\Tech\2015.MessageIDs.ftx documents the message-ID convention.


12. Configuration, flavors, and feature bits at runtime

Startup sequence (simplified):

  1. Flux.exe starts (entry in Flux.App).

  2. Reads Flux.flavor next to the EXE → picks a EFlavor value.

  3. Loads feature bits from the flavor (e.g. Bend, Laser, Punch, Trumpf).

  4. Validates licensing (Aegis or Trumpf WIBU/Sentinel, depending on flavor).

  5. Locates the data folder (FLUXDATA env var on dev machines, C:\ProgramData\… on installed flavors).

  6. Loads the wad (FLUXWAD env var or Flux.wad next to the EXE).

  7. Bootstraps Hub slots, opens the main window.

  8. Restores last-open documents (Engine flavor: skips UI bootstrap entirely).

Code paths to inspect:

  • Solution startup project: Flux.App → main entry typically named App.cs or similar.

  • Notes\Tech\2013.FluxFlavors.ftx for the feature-bit table.

  • Notes\Tech\2009.FluxConfiguration.ftx for configuration.


13. Cross-cutting modules at a glance

Cross-cutting Where Touchpoints

Settings (Sheaf)

Src\Core\Settings\Sheaf.cs

Every domain object via ISheafSite

Hub (DI)

Src\Core\Hub.cs

App fills slots; Core/UI invoke them

Rendering (Lux)

Src\Base\Lux\

Every VModel.Draw() method

Undo

Src\Base\Undo\

Globs and BA.Set helper

Persistence (Au/Curl)

Src\Base\Gold\, Notes\Dev\1003.AuGoldEncoding.ftx

All persisted models

IO formats

Src\Core\IO\

Per-format Reader/Writer

Licensing

Src\Lib\ (NuPkgs) + per-flavor wiring

App startup

Flux.wad

X:\Wad\ and Flux.wad zip

Resource loader at startup

Logging / messages

FX.Out, Notes\Tech\2015.MessageIDs.ftx

Pervasive


14. The architecture’s three pain points (be aware)

  1. The dual crash engines in Bend (BendOpCrash.cs vs. NBendCrash.cs) — both alive, both ~70 KB. A migration in flight; treat with care.

  2. partial classes spanning many files. BendOp (210 KB) is one example; BendTech and Part are similar. A Grep for a method name will lead you to the right partial — but the whole class lives across files.

  3. Static singletons (Part.Current, BendMachine.Default, Hub.).* These are not unit-testable in isolation. The Flit framework works around it by setting BA.Testing = true and substituting fixtures — BendMachine.Default returns machine 99 in test mode for that reason.


15. Self-check questions

After this chapter you should be able to answer all of these without looking back. If not, re-read the relevant section.

  1. Why are model and VModel in the same assembly? (§3)

  2. How does Core invoke a UI dialog without a project reference to UI? (§6 — Hub)

  3. What does ISheafSite.SHParent give you, in one sentence? (§5)

  4. Where does VModel.Draw() actually draw to? (§7)

  5. If a bug only appears on Trumpf machines, which two files are likely involved? (§4 of chapter 02 — BendCalc switch via IsTrumpf)

  6. How does the Engine flavor (no UI) avoid bootstrapping WPF? (§6 + §12 — null Hub slots, no main window)

  7. After deserializing an old BendSetup, how does it forward-migrate? (§8 — [PostLoad])

  8. What happens when the user has multiple bends selected and edits one property? (§4 — composite Glob)


16. Reading order for chapter 01

If you’re reading these notes for the first time, do this in order:

  1. Notes\Dev\1002.BuildingFlux.ftx lines 31—​95 (the architecture rationale).

  2. Src\Core\Hub.cs — skim, see the slot pattern.

  3. Src\Core\Settings\Sheaf.cs lines 1—​80 — the cascade.

  4. Src\Base\Lux\VModel.cs lines 1—​80 — the render base.

  5. Src\Core\Part\Part.cs lines 1—​80 — the part aggregate.

That’s about 30 minutes of focused reading and gives you the spine of the system.


17. If you take just one thing from this chapter

Flux is built around a Part aggregate that owns multiple *Tech projections (BendTech, FoldTech, CutTech). Cross-cutting state is reached through Hub (DI) and Sheaf (settings). Rendering is Lux. Once you internalize those four words — Part, Tech, Hub, Sheaf — the whole codebase becomes navigable.


Last updated: 2026-05-04. Verified against Src\Core\Hub.cs, Src\Core\Settings\Sheaf.cs, Src\Base\Lux\VModel.cs, Src\Core\Part\Part.cs, and Notes 1002/1003/1005/2013/2015.

Contents

  • 1. The big picture in three diagrams
  • 1.1 Static module dependencies
  • 1.2 Runtime layers (a single Flux process)
  • 1.3 Pipeline for a typical CAM job
  • 2. The five layers explained
  • 2.1 Flux.Base — foundations
  • 2.2 Flux.Core — the CAM engine
  • 2.3 Flux.UI — the controllers
  • 2.4 Flux.App — the shell
  • 2.5 Flux.API — the controlled exposure
  • 3. Why model and view live together
  • 4. The Glob system — controllers in detail
  • 5. The Sheaf — cascaded settings everywhere
  • 6. The Hub — wiring layers without circular dependencies
  • 7. Rendering — the Lux pipeline
  • The lifecycle of a VModel
  • Why this matters for debugging
  • 8. Persistence model
  • [PostLoad] — the migration hook
  • 9. Threading model
  • 10. Undo / redo
  • 11. Errors, logging, and "FX"
  • 12. Configuration, flavors, and feature bits at runtime
  • 13. Cross-cutting modules at a glance
  • 14. The architecture’s three pain points (be aware)
  • 15. Self-check questions
  • 16. Reading order for chapter 01
  • 17. If you take just one thing from this chapter
Welcome & Repo Map Subsystem *Bend* (Press Brake)

      Copyright © 2025 TRUMPF Metamation. All rights reserved.

    Compiled by Bento