Skip to content

Authoring Layouts

EmoTracker Community edited this page Apr 8, 2026 · 2 revisions

Authoring Layouts

This page describes the layouts JSON format that EmoTracker packs use to declare every visual arrangement on screen — the items grid, the map view, the broadcast view, the popups behind buttons, the contents of pinned-location cards, and so on.

It's the top of a small hierarchy: read this page first for the general format, the base fields shared by every element, and the layout-engine concepts that aren't tied to one element type. Then jump to the per-element sub-pages for the specific options each element accepts.

New to pack authoring? Read Developer Setup first to wire up VS Code schema validation, then Authoring Items and Authoring Locations — layouts reference items and locations by code, so you'll typically have those declared before you start arranging them visually.

What a layout is

A layout is a tree of layout elements that EmoTracker renders as one logical "view". Some layouts are tied to specific UI surfaces:

Layout name Where it's shown
tracker_default The main tracker window's primary view
tracker_horizontal The main tracker window when it's wider than it is tall
tracker_vertical The main tracker window when it's taller than it is wide
tracker_broadcast The Broadcast View window
tracker_capture_item The default item picker for section capture slots

Other layouts are loaded by name and referenced from somewhere else — typically from a Layout Reference inside a parent layout, or from a Button Popup, or from a section's capture_item_layout field.

The runtime maintains all loaded layouts in LayoutManager, keyed by their name. When EmoTracker needs a layout (e.g., the main window starts up), it asks the manager for the layout with the matching name. If you don't define one, the surface falls back to whatever default the runtime chooses (or nothing).

Where layouts files live

Layouts are loaded from Lua at pack init time:

-- scripts/init.lua
Tracker:AddLayouts("layouts/tracker.json")
Tracker:AddLayouts("layouts/popups.json")
  • Paths are relative to the pack root.
  • You can split layouts across as many files as you like. Names must be unique across the whole pack — duplicate names are silently ignored after the first.
  • Legacy packs may use a single root-level tracker_layout.json, which EmoTracker still loads automatically. New packs should use explicit Tracker:AddLayouts(...) calls.
  • Items and locations should generally be loaded before layouts, since item elements look up items by code at parse time and map elements need maps to be registered. (Some elements like Layout Reference tolerate late binding, but parse order matters more for layouts than for the other systems.)

Top-level structure

Unlike items and locations files (which are arrays), a layouts file is a JSON object at the top level, where each key is the layout name and each value is the root layout element:

{
  "tracker_default": {
    "type": "container",
    "content": {
      "type": "itemgrid",
      "rows": [
        [ "sword", "shield", "bow", "boomerang" ],
        [ "hookshot", "lamp", "hammer", "shovel" ]
      ]
    }
  },

  "tracker_capture_item": {
    "type": "container",
    "content": { ... }
  }
}

Each value is a single root layout element. The element can be any type — typically a Container or one of the panel types (Array, Dock, Canvas, etc.) — and that root element's children form the rest of the tree.

The canonical schema is published in EmoTracker-Service/sdk/schema/layouts.json. Wire it up in VS Code via Developer Setup → Configuring JSON schema validation so you get autocomplete for every element type and field as you author.

Fields every layout element shares

All elements inherit a common set of base fields, parsed in EmoTracker.Data/Layout/LayoutItem.cs:TryParse. These cascade through every type listed below.

Identity

Field Type Default Description
type string required The element type — picks one of the parsers (container, array, image, etc.). See Layout element types below.
uid string none Optional unique identifier for this element. If set, the element is registered with LayoutManager and can be looked up at runtime by other code.

Visual properties

Field Type Default Description
background string none Background color in web color format (#rrggbb or #aarrggbb for alpha).
foreground string none Foreground color in the same format.
dropshadow boolean false Apply a drop-shadow effect to this element when shown in the main window.
broadcast_shadow boolean false Apply a drop-shadow effect to this element when shown in the Broadcast View window. (Independent of dropshadow.)
hit_test_visible boolean true If false, the element and its children ignore mouse input — clicks pass through to whatever is behind them.

Sizing

Field Type Default Description
width number auto Fixed width in layout units.
height number auto Fixed height.
min_width number none Lower bound.
min_height number none Lower bound.
max_width number none Upper bound.
max_height number none Upper bound.
scale number 1.0 Multiplier applied to the element's measured size. Useful for scaling subtrees up or down.

Any size field with a value < 0 (the default sentinel) is treated as "not set" — the runtime falls back to auto-sizing based on the element's content and its parent's layout rules.

Positioning

Field Type Default Description
margin string "0" Outer margin. Can be 1, 2, or 4 numbers separated by commas: "5" (uniform), "5, 10" (horizontal, vertical), "5, 10, 5, 10" (left, top, right, bottom).
h_alignment string "stretch" Horizontal alignment within the parent's allocated slot: left, center, right, stretch.
v_alignment string "stretch" Vertical alignment within the parent's allocated slot: top, center, bottom, stretch.
dock string none When the parent is a Dock Panel, pins this element to that edge: left, right, top, bottom. The first child without a dock value fills any remaining space.
canvas_left number none When the parent is a Canvas Panel, the X coordinate of this element's top-left corner.
canvas_top number none When the parent is a Canvas Panel, the Y coordinate of this element's top-left corner.
canvas_depth number none Z-order within the Canvas Panel. Higher values draw on top.

About swap_left_right

If the user has the Swap Left/Right option enabled in their EmoTracker settings, the runtime automatically swaps:

  • dock: "left"dock: "right" for every element it parses
  • The first and third comma values in any 4-number margin (so left and right margins also swap)

You don't have to do anything to support it — your layout will mirror itself for users who flip the switch.

Loading order and uid

The base TryParse runs before each element's type-specific parser, which means:

  • A uid is registered immediately, so an element can reference its own uid from script later in the same load.
  • Layout-element references (like a Button Popup's layout field, or a Layout Reference's key field) resolve at parse time too — so the referenced layout has to already exist when the referencing element is parsed.

The practical implication: load referenced layouts before the layouts that reference them. The simplest pattern is to load a popups.json file containing all your popup layouts before the main tracker.json that references them.

Layout element types

Pick the sub-page for the element you're authoring. Each sub-page documents its JSON fields, behavior, and at least one example.

Containers (have content children)

Type What it's for Sub-page
container / grid A simple wrapper around one or more children. Multiple children stack on top of each other. Container
viewbox A container that scales its child to fit the available space. Container → ViewBox
array A horizontal or vertical list of children. Array
canvas Free-form positioning of children using canvas_left / canvas_top. Canvas
dock Children docked to edges, with the last child filling the remainder. Dock
group A container with a header bar above its children. Group
scroll A container with scrollbars when its content overflows. Scroll
tabbed A tabbed view where each tab contains its own layout. Tabbed
button_popup A button that, when clicked, displays another layout in a popup. Button Popup

Leaf elements (no children)

Type What it's for Sub-page
item A single item lookup by code. Item
itemgrid A regular grid of items, declared row-by-row. Item Grid
image A static image, optionally filtered. Image
text A static text label. Text
map One or more of the pack's maps. Map
layout A reference to another loaded layout, embedded inline. Layout Reference
recentpins / recent_pins A list of recently pinned locations. Recent Pinned Locations
last_cleared_location A display of the most recently cleared location. Last Cleared Location

The schema currently lists the main 14 types but a few additional ones (text, viewbox, last_cleared_location) are accepted by the parser even though they're not in the schema's enum field. They're documented on this wiki because they work — you may see schema-validation warnings in your editor when you use them.

See also

Clone this wiki locally