Editing menus with an addon ​

Where things sit on a menu screen is stored in the screen's scene, an .idf in the game's UI archives. To move elements or add a slot, edit the scene in Swofty UI, export it, and ship the exported .idf in an addon with one replace-resource ERP operation per archive that holds the scene.

1. Open the scene ​

Start Swofty UI and press Ctrl+K. Search for the screen by file name or folder, such as rnd_overview or career laptop, and press Enter. The title bar shows the scene's path, and the archive picker beside it lists every archive that holds it.

Swofty UI reads the archives in the game folder as they are. After swofty apply, those include your own edits; run swofty restore first to start from stock.

2. Edit it ​

Select an element on the canvas or in the hierarchy, then:

  • drag it, or nudge it with the arrow keys, to move it;
  • type a new position, scale, rotation or param value in the inspector;
  • press Ctrl+D to clone it as a new sibling, with a new name and the ids it needs;
  • rename it in the inspector, or press Del to delete it;
  • for an eXRef, type another scene's path in the inspector's XRef section and press Retarget to make it draw that scene.

Every edit goes in the Edits list, and Ctrl+Z undoes it. Before moving an element, look for an Anims section in the inspector: an animated element's position is replaced when its animation plays, so move its unanimated children instead.

3. Export ​

Press Ctrl+S. Swofty UI writes the scene, checks it, and saves three files to its export folder:

FileContents
rnd_overview.idfThe edited scene
rnd_overview.erp.jsonAn ERP operations file: one replace-resource per archive that holds the scene
rnd_overview.edits.jsonThe edit list, the source scene and archive, and the SHA-1 of the source and the export

4. Add it to your addon ​

Put the .idf in your addon's ui/ folder and the operations file in erp/:

text
my-addon/
├── swofty.json
├── erp/
│   └── scenes.json          (rnd_overview.erp.json)
└── ui/
    └── rnd_overview.idf
json
{
  "schema_version": 1,
  "ops": [
    {
      "op": "replace-resource",
      "erp": "2025_asset_groups/ui_package/flow_career_hub.erp",
      "resource": "eaid://ui_package/art/screens/career/rnd_overview.idf",
      "source": "ui/rnd_overview.idf"
    },
    {
      "op": "replace-resource",
      "erp": "2025_asset_groups/ui_package/flow_team_hq.erp",
      "resource": "eaid://ui_package/art/screens/career/rnd_overview.idf",
      "source": "ui/rnd_overview.idf"
    }
  ]
}

List the operations file under operations.erp in the manifest:

json
{
  "schema_version": 1,
  "id": "author.rnd-layout",
  "name": "R&D layout",
  "version": "1.0.0",
  "author": "Your Name",
  "compat": { "game": "f1_25" },
  "kind": ["erp"],
  "operations": { "erp": ["erp/scenes.json"] }
}

Each replace-resource replaces the scene's single fragment in one archive. Keep every archive Swofty UI listed: the game reads a scene from whichever archive loads it first.

5. Build and play ​

sh
swofty addons install ./my-addon
swofty addons enable author.rnd-layout
swofty build

Then press Play in the launcher. The build:

  1. Checks that each source is a scene saved from the same .idf, by its componentId, and fails otherwise:

    text
    the source is scene 0x…, this resource is scene 0xbe419b0b8324e33c; it was saved from another .idf
  2. Writes the new fragment, recompresses it, and updates the archive's sizes, offsets and hashes. Every other resource is copied byte for byte.

  3. Delivers the archive. The in-game loader's overlay only carries a replacement with the stock fragment size; an edited scene usually changes size, so the build writes those archives into the game files through the journal and prints:

    text
    erp: 2025_asset_groups/ui_package/flow_career_hub.erp built into the game files; 1 resource(s) change their stock layout, which the in-game loader cannot load, such as eaid://ui_package/art/screens/career/rnd_overview.idf: fragment 0 is 30108 bytes, the stock one 29596; …
  4. Warns when another stock archive in the same folder also holds the resized scene and your addon doesn't replace it there.

The launcher restores the rewritten archives when the game exits. swofty restore puts them back by hand, such as after swofty apply or a crash. See ERP operations for the operation itself.

Limits ​

  • Live data needs .ui wiring or native code. A scene holds rectangles, not content. Text, numbers, lists and colours come from the .ui node attached to an element and the view model behind it. A new element stays empty until a node attaches to its name, either in the screen's .ui or built by an engine plugin. Data the screen's view model doesn't publish needs native code.
  • Animations and stackers override stored positions. An animated element takes its transform from its clip while the clip plays. An eStacker lays out its children at runtime, so a child's stored position is replaced; a child added to a stacker is placed with the rest.
  • New art needs new textures or meshes. A scene can reuse art: a clone keeps its geoms, and an eXRef can point at another scene. A new image is a new texture resource (Textures and models), and a new shape, such as a narrower pie wedge, is a new mesh.
  • A reference loads the scene its xref id names. The game finds an eXRef's scene by its xref id, the md5-64 of the scene's path, not by its fileRef path. A scene written by another tool with a new fileRef and the old xref still shows the old scene in game. Swofty UI draws the scene the id names, marks the mismatch and refuses to export it; see References.
  • A scene replaces the whole stock scene. When a game update changes a scene your addon ships, export it again from the new stock scene. The .edits.json holds your edits for replaying them.

Next ​

Publishing