Single-element SVGs (like FIO paths) were exported as bare <path>
without tagpaths/color/state/priority. Now all symbols are wrapped
in a <g> group with the Ignition data attributes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These are infrastructure/special devices that don't use standard
color/state/priority bindings. EPC has specialized stroke bindings,
MCM has unique structure, FIO/SIO are network nodes without
operational state displays.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DPM: only elements[1] gets fill.paint binding (black triangle),
elements[0] and [2] keep their static colors.
Buttons (JR, S, SS, EN): no elements[0].fill.paint binding —
background rect keeps static color. Only text gets contrast binding.
Tag paths: strip _PB/_SPB/_STPB suffixes from button labels to
match PLC naming (UL17_19_S1 not UL17_19_S1_PB).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Users can rotate any symbol manually — the pre-rotated _v variants
were redundant. Removed from SYMBOLS array, PRIORITY_TYPES,
SPACING_EXEMPT, RECT_CONVEYANCE, OVERLAY_IDS, OUTDATED_SIZES,
and all type-check functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extracts all CDW5_SCADA boilerplate (zoom controls, markdown tooltip,
pan/wheel events, element color/state/priority tag bindings, display
filters, Start/Stop special-case bindings) into a new ignition-view.ts
module. deployToIgnition() now produces the complete view.json instead
of a minimal skeleton. Also adds ignitionViewPath to the store/toolbar
and routes it through the deploy endpoint so views land under the correct
sub-folder (e.g. DetailedView/MCM09).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract parseConveyanceLabel to shared label-utils.ts (was duplicated)
- Add EXTENDO_CONFIG, LABEL_CONFIG, CONVEYANCE_STYLE to symbol-config.ts
- Replace all hardcoded fill/stroke/lineWidth with CONVEYANCE_STYLE
- Replace magic font numbers (14, 4, 0.5) with LABEL_CONFIG constants
- Extract drawSpurSymbol, drawExtendoSymbol, drawRectConveyanceSymbol
from inline code — drawSymbolBody is now a clean dispatch
- Convert getIgnitionTagPath from 18 if-statements to data-driven table
- Add THEME.marquee for selection rectangle colors
- Remove no-op assignment in parseConveyanceLabel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All small/overlay devices (PE, FIO, BCN, SOL, JR, S, SS, EPC, DPM,
PDP, MCM, PS, diverter, camera) render LAST so they're on top of
conveyors and clickable in SCADA.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ignition's JSON parser can't handle ISO timestamps with milliseconds
(2026-03-30T19:31:53.623Z). Strip to seconds (2026-03-30T19:31:53Z).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ignition requires this signature to validate resource integrity.
Without it, the Designer fails with "Error reading updated project".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deleting the folder caused Ignition's ResourceTreeFileWatcher to error
when cleaning up cached resource copies. Now just overwrites in place.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deploy now attempts to trigger a scanProject message handler after
writing files. Requires a Gateway Message Handler named "scanProject"
in Ignition Designer with: IgnitionGateway.get().getProjectManager().requestScan()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Working Ignition views only have meta, position, props, type on child
components — no version or custom fields.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Component gets meta.name + position at same level as type/props
- Root container uses props.mode="percent" not direction="column"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New "Ignition" section in toolbar with Project and View name fields
- View name defaults to current MCM
- "Deploy to Ignition" button writes view.json + resource.json to:
C:/Program Files/Inductive Automation/Ignition/data/projects/{Project}/
com.inductiveautomation.perspective/views/{ViewName}/
- Vite dev server plugin handles file writing via /api/deploy-ignition
- view.json wraps ia.shapes.svg component in proper Perspective view structure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New "SCADA" button generates Ignition-compatible JSON that can be
directly pasted into Ignition Perspective views. Converts SVG elements
to Ignition's ia.shapes.svg JSON format with:
- Proper element types (group, rect, path, text, polyline, circle)
- Fill/stroke as {paint, width} objects
- Text style as {fontFamily, fontWeight, fontSize} objects
- color, state, priority, tagpaths as top-level element properties
- Correct viewBox, meta, position structure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each symbol gets data-* attributes for Ignition integration:
- data-color="#000000", data-state="OFF", data-priority="No Alarms"
- data-tagpath="System/{MCM}/{Category}/{SubType}/{Label}"
Tag paths derived from label suffix (_VFD→VFD/APF, _TPE→Sensor/Tracking, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Spur was using availH=h (no padding) giving 14px, while conveyors
used availH=h-4 giving 13px. Now both use the same padding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous min() was wrong — pushed text further right when text was
wider than available space. Now uses max() to keep text left-aligned
within the trapezoid while right edge stays at the angled boundary.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Measure actual text width and position so the right side of the text
aligns with the angled edge of the spur, preventing overflow onto
adjacent conveyors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Position text at 55% height (toward wider area), then center
horizontally based on the actual right edge at the text's top,
minimizing overflow past the angled edge.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 90-degree corners are at x=0 in local coords. The rectangular
region from x=0 to x=min(w2,w) always fits inside the trapezoid.
Text is centered in this safe zone — on the straight-edge side,
not the angled side.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shift text toward the bottom-right corner of the trapezoid where
the right angle creates the most open space for the label.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Text centered at x = (w2 + w) / 2 — the middle of the wide right
portion of the trapezoid where there's the most space.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Place text centered at the wide bottom edge where there's always
enough room. No font shrinking — the wide end has plenty of space.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Center text at 75% of trapezoid height where the shape is widest,
using the actual width at that height for proper fit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Center text at vertical midpoint, shifted right toward the wider end
where there's more horizontal space. Uses 55% of the mid-height width
as center position and 85% as available width.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move text to 65% from top (wider end) so it fits without shrinking
- Fix effective angle for mirrored symbols: use (360-rot) to determine
if flip is needed, preventing incorrect upside-down detection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Position text at 40% from top (toward narrow end) and constrain width
to the narrower edge so text never overflows the trapezoid shape.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mirrored symbols need text counter-mirrored (scale -1,1) to prevent
backwards text. Restored mirror fix that was incorrectly removed.
Applied to both canvas renderer and SVG export.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ignition strips font-weight/font-family/font-size as separate SVG
attributes but preserves them inside style="..." CSS. Moved all text
styling to inline style for conveyance labels and BCN/SOL/PDP symbols.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace dominant-baseline="central" (unsupported in Ignition) with
manual y offset (10 -> 12.8) for proper vertical centering of text
inside these symbol boxes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Labels now follow the mirrored shape naturally — text mirrors
along with the conveyor/shape as the user expects.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Canvas renderer:
- Straight/spur: flip text 180 when rotation is 91-269 deg
- Mirror: counter-scale text so it doesn't read backwards
- Curved: compute world angle (sym rotation + tangent), flip if upside-down
SVG export:
- Curved text now includes rotation transform along the arc tangent
- Straight text includes rotation correction for readability
- All text stays grouped with its shape for proper transform inheritance
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap each conveyance shape + its label text in a <g> element so
rotation/mirror transforms apply to both shape and text together
- Change stroke-width from 0.5 to 1 on all conveyance and PE shapes
(both canvas renderer and SVG export)
- Text is now inside the group, inheriting the transform — no more
floating unrotated labels
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toolbar:
- Compact project/MCM selectors always visible at top
- Action bar (SVG, JSON, Import, Clear) as compact button strip
- Cleaner section toggles with minimal chrome
- Inline settings rows (W/H and Grid/Gap on one line each)
- Narrower width (220px vs 240px)
Palette:
- Group headers are collapsible (start collapsed to save space)
- Small symbols (Controls, Sensors, I/O, Other) use 2-column grid
- Conveyance keeps list layout (wider items)
- Lighter, less cluttered item styling
- Custom scrollbar
Color scheme:
- Shifted from navy/red (#16213e/#e94560) to slate/blue (#111827/#3b82f6)
- Better contrast and more professional feel
- DeviceDock updated to match
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SVG export now embeds layout JSON as HTML comment for re-import
- New loadLayoutSVG() extracts embedded data from exported SVGs
- Import accepts both .json and .svg files
- New exportJSON() saves layout as MCM_layout.json
- JSON export button added to toolbar
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>