Feature: Tiled Track Editor
Feature: Tiled Track Editor
Idea history
Was discussed in JMRI ML "[jmri-developers] Track Tiles: New panel type vs new function in existing panel" started 2025-11-22.
Main takeaway:
- Generally welcome feature but mind existing attempts at interop with xtrkcad or anyrail (Bob, Heiko)
- Best implement it as extension of the existing Layout Editor Panel types. (Bob, Eckart)
- Tile libraries are best defined in XML. Explore if existing tile definition formats can be used. Make it easy for community to add tile types (Daniel) Borrow concepts from how JMRI’s Signal Systems are structured with single-definition files in directories, etc?
- Mind sawn-off of customized parts (whmvd)
- Mind flex tracks, easement, wedges, natural slop
- Base off existing LayoutXXXX object types. Keep ability to visually compress on screen sizes independent of physical sizes (Steve G)
- List suggested providing an XML schema rather than a DTD for the tracktiles library.
Concept: Tiled Tracks in Layout Editor
Construct JMRI layouts from fixed geometry off the shelf parts from different vendors (i.e. Marklin, Piko, Kato, ...) with JMRI automatically recognizing physical angles, lengths, potential wiggle rooms / tolerance for gaps between parts or unclean connection angles. By default draws layout to scale (i.e. 1 cm physical length maps whatever number of squares represents 1 cm of panel length. Keep ability to display out of scale lengths.
User interface.
Select a track element. Hold shift and click a layout point (either a free anchor or an existing track element). If the point was an empty anchor or adjecant to an untiled/generic JMRI element, select a second anchor point for orientation. If the point was adjacent to a tiled element, automatically create a target point based on the element's geometry assuming 0 slop or easement. Auto-select the free end of the new tile. In case of turnouts, continue from the default / straight point. Provide a "repeat" hot key which adds the same element to the free side if the newly added element.
Object and Data Model
A straight or curved tile is a TrackSegment/LayoutTrack with a TileDefinition pointer. Attributes for physical dimensions and position are filled from tile definition defaults.
A turnout tile is a LayoutTurnout/LayoutTrack with a tile definition pointer.
As I understand it, persistence logic must be amended for new properties at the individual ViewXml classes - however, shared properties can be inherited from base classes. I.e. LayoutLHTurnoutViewXml inherits from LayoutTurnoutViewXml, LayoutTrackViewXml, AbstractXmlAdapter so duplication can be kept to a minimum.
The TileDefinition pointer should never be null value but default to a GenericJmri type which can be constructed without parameters and suffices a common interface.
Upgrade Behaviour
When loading an older JMRI XML file, all LayoutTrack elements should get a TileDefinition of GenericJmri
Downgrade behaviour
To be tested: When downgrading to an older JMRI file, LayoutTracks and their properties will probably just be ignored and tiles will just function as many small Track or Turnout elements with connectors.
When downgrading to a JMRI version with tile element feature which does not have a specific tile, unavailable tile definitions should degrade to a generic UnavailableTile so JMRI does not crash during upgrade/downgrade testing and layouts can be shared. For all intents and purposes and UnavailableTile should work like a generic JMRI tile but be marked as an issue.
Interop with xtrkcad
To be explored. Built a minimum Lego Gauge layout with LHS and RHS turnout, two-track station and a straight track at the opposing side. Inspected track definition file and layout save file. Both use a non-XML tab indented format for describing tracks. XtrkCadReader from JMRI should have the necessary code to understand this format.
So far it looks like interop between Tiles functionality and xtrkcad's tiles libraries can be only superficial. Their tiles are named in their layout format and JMRI must match that either to an available tile definition or to an UnavailableTile which just imports the defined properties.
Development approach
Start with straight and fixed radius tiles first: Data model, upgrade/downgrade logic, two incomplete sample libraries with 5-10 elements each. Individual feature branches should be mergeable piecemeal into JMRI without breaking functionality.
Each new iteration should be covered with reasonable amount of unit tests but not necessarily "feature complete". Demonstrate safe downgrading and upgrading of layouts with each substantial addition.
Link to the discussion on the JMRI developers list: https://jmri-developers.groups.io/g/jmri/topic/116420939
Short summary of progress:
Done
- Two halfway complete tile libraries for PIKO A-Track and MARKLIN C-Track and a schema for tracktiles have been built. Both schema and libraries are still evolving.
- Positioning straight and curved track tiles works
- Editor now supports dragging and releasing from an anchor point to a cursor position. For non-tile (traditional) tracks, this implicitly creates an anchor point at release position if missing. In tile mode this implicitly creates an anchor point at the direction/angle of release relative to the starting anchor point, but at the fixed length of the tile.
- Editor "scale" dialog was amended to define different ratios between real-world cm/inch and on screen squares
- "orientation wrt grid (degrees) at anchor point" and "path length" have been implemented for tile-based straights and curved tiles. A reusable UI widget has been created to also support multi-path tiles (turnouts etc) but currently only works correctly for TrackSegments.
- Some unit tests. Coverage is worse than I intended after I moved some placing, sizing and rotation geometry down from the views to the models.
In progress
-
Due to the demand that physical tiles work coherently but integrate with the existing layout logic (allowing to distort onscreen presentation of track elements for maximum usefulness), coordinate system for display needs to be decoupled from "physical" geometry. This also resolves some ambiguity.
-
Some occurances of "abstract in base class, stubs in most implementations" have been changed into optional interfaces.
-
Rotating and scaling JMRI turnouts, slips, crossings, X-overs turned out to be more involved than anticipated. Basic "connect to existing anchor" functionality is provided but rotation and scaling needs to be added.