GFF GUI - OpenKotOR/PyKotor GitHub Wiki
GUI — Graphical User Interface
GUI files define the layout and behavior of every in-game interface screen — menus, HUD elements, dialog panels, and character sheets (GUI L154, GFFContent.GUI L163). Each GUI is a GFF tree describing a hierarchy of panels, buttons, labels, sliders, and other controls, with properties controlling position, size, textures, and event bindings (GUIControl L100, construct_gui L349, read_gui L1060, GFF binary reader io_gff.py L82). Other implementations handle GUI as a standard GFF structure: reone gff.cpp, KotOR.js GFFObject.ts L24, Kotor.NET GFF.cs L18.
GUI controls reference TPC/TGA textures for visual elements and use TLK string references for localizable text; the GUI editor in the Holocron Toolset covers the full editing workflow.
Core Identity fields
| Field | Type | Description |
|---|---|---|
Tag |
CExoString | Unique GUI identifier |
ObjName |
CExoString | Object name (unused) |
Comment |
CExoString | Developer comment |
Control structure
GUI files contain a Controls list that holds the top-level UI elements (GUIControl L100, KotOR.js GFFObject.ts L24). Each control can contain child controls, forming a tree structure.
| Field | Type | Description |
|---|---|---|
Controls |
List | List of child controls |
Type |
int32 | Control type identifier |
ID |
int32 | Unique control ID |
Tag |
CExoString | Control tag |
Control types [gui.py GUIControlType L23, reone types.h L23, KotOR.js GUIControlType.ts]:
⚠ Note: PyKotor assigns 4=ProtoItem, 5=Label; reone and KotOR.js assign 4=Label, 5=ProtoItem/ImageButton. The discrepancy exists across implementations — use the
TAGfield for reliable control lookup.
| ID | Name (reone/KotOR.js) | Name (PyKotor) | Description |
|---|---|---|---|
| -1 | Invalid | Invalid | Invalid control type |
| 0 | Control | Control | Base container |
| 2 | Panel | Panel | Background panel/container |
| 4 | Label | ProtoItem | Static text label (reone/KotOR.js); ProtoItem template (PyKotor) |
| 5 | ProtoItem/ImageButton | Label | ProtoItem template (reone/KotOR.js); Static text label (PyKotor) |
| 6 | Button | Button | Clickable button |
| 7 | ToggleButton/CheckBox | CheckBox | Toggle checkbox |
| 8 | Slider | Slider | Sliding value control |
| 9 | ScrollBar | ScrollBar | Scroll bar control |
| 10 | ProgressBar | Progress | Progress bar indicator |
| 11 | ListBox | ListBox | List of items with scrolling |
Common Properties
All controls share these base properties:
| Field | Type | Description |
|---|---|---|
CONTROLTYPE |
int32 | Control type identifier (see Control types) |
ID |
int32 | Unique control ID for script references |
TAG |
CExoString | Control tag identifier |
Obj_Locked |
byte | Lock state (0=unlocked, 1=locked) |
Obj_Parent |
CExoString | Parent control tag (for hierarchy) |
Obj_ParentID |
int32 | Parent control ID (for hierarchy) |
ALPHA |
float | Opacity/transparency (0.0=transparent, 1.0=opaque) |
COLOR |
vector | Control color modulation (RGB, 0.0-1.0) |
EXTENT |
Struct | position and size rectangle |
BORDER |
Struct | Border rendering properties |
HILIGHT |
Struct | Highlight appearance (hover state) |
TEXT |
Struct | Text display properties |
MOVETO |
Struct | D-pad navigation targets |
EXTENT Struct:
| Field | Type | Description |
|---|---|---|
LEFT |
int32 | X position relative to parent (pixels) |
TOP |
int32 | Y position relative to parent (pixels) |
WIDTH |
int32 | Control width (pixels) |
HEIGHT |
int32 | Control height (pixels) |
Positioning System:
- coordinates are relative to parent control
- Base resolution is 640x480, scaled for higher resolutions
- Negative values allowed for positioning outside parent bounds
- Root control (GUI) uses screen-relative coordinates
BORDER Struct:
| Field | Type | Description |
|---|---|---|
CORNER |
ResRef | Corner texture (TPC or TGA) |
EDGE |
ResRef | edge texture (TPC or TGA) |
FILL |
ResRef | Fill/background texture (TPC or TGA) |
FILLSTYLE |
int32 | Fill rendering style integer; default 2 in BORDER [gui.py L461], 0 in HILIGHT/PROGRESS [gui.py L408]; reone and xoreos read as raw uint [xoreos widget.cpp L532] |
DIMENSION |
int32 | Border thickness in pixels |
INNEROFFSET |
int32 | Inner padding X-axis (pixels) |
INNEROFFSETY |
int32 | Inner padding Y-axis (pixels, optional) |
COLOR |
vector | Border color modulation (RGB, 0.0-1.0) |
PULSING |
byte | Pulsing animation flag (0=off, 1=on) |
Border Rendering:
- CORNER: 4 corner pieces (top-left, top-right, bottom-left, bottom-right)
- edge: 4 edge pieces (top, right, bottom, left)
- FILL: Center fill area (scaled to fit)
- DIMENSION: Thickness of border edges
- FILLSTYLE: Raw integer read by engine; default 2 for BORDER [
gui.pyL461]; no named enum exists in reone or xoreos sources - CORNER/EDGE/FILL textures: skipped if empty or if the value is the string
"0"[reonecontrol.cpploadBorder]
TEXT Struct:
| Field | Type | Description |
|---|---|---|
TEXT |
CExoString | Direct text content (overrides StrRef if set) |
STRREF |
DWord | TLK string reference (0xFFFFFFFF = unused) |
FONT |
ResRef | Font texture resource (TPC or TGA) |
ALIGNMENT |
int32 | Text alignment flags (bitfield) |
COLOR |
vector | Text color (RGB, 0.0-1.0) |
PULSING |
byte | Pulsing animation flag (0=off, 1=on) |
Text Alignment values:
- 1: Top-Left
- 2: Top-Center
- 3: Top-Right
- 17: Center-Left
- 18: Center (most common)
- 19: Center-Right
- 33: Bottom-Left
- 34: Bottom-Center
- 35: Bottom-Right
Text Resolution:
- If both
TEXTandSTRREFare set,TEXTtakes precedence - Font textures contain character glyphs in fixed grid
- Text color modulates font texture (white = full color, black = no color)
MOVETO Struct:
| Field | Type | Description |
|---|---|---|
UP |
int32 | Control ID to navigate to when pressing Up |
DOWN |
int32 | Control ID to navigate to when pressing Down |
LEFT |
int32 | Control ID to navigate to when pressing Left |
RIGHT |
int32 | Control ID to navigate to when pressing Right |
Navigation System:
- Used for keyboard/D-pad navigation
- value of -1 or 0 indicates no navigation in that direction
- Essential for controller/keyboard-only gameplay
HILIGHT Struct:
| Field | Type | Description |
|---|---|---|
CORNER |
ResRef | Corner texture for highlight state |
EDGE |
ResRef | edge texture for highlight state |
FILL |
ResRef | Fill texture for highlight state |
FILLSTYLE |
int32 | Fill style for highlight |
DIMENSION |
int32 | Border thickness |
INNEROFFSET |
int32 | Inner padding X-axis |
INNEROFFSETY |
int32 | Inner padding Y-axis (optional) |
COLOR |
vector | Highlight color modulation |
PULSING |
byte | Pulsing animation flag |
Highlight Behavior:
- Shown when mouse hovers over control
- Replaces or overlays BORDER when active
- Used for interactive feedback
- color typically brighter/more saturated than border
SELECTED Struct:
| Field | Type | Description |
|---|---|---|
CORNER |
ResRef | Corner texture for selected state |
EDGE |
ResRef | edge texture for selected state |
FILL |
ResRef | Fill texture for selected state |
FILLSTYLE |
int32 | Fill style for selected state |
DIMENSION |
int32 | Border thickness |
INNEROFFSET |
int32 | Inner padding X-axis |
INNEROFFSETY |
int32 | Inner padding Y-axis (optional) |
COLOR |
vector | Selected state color modulation |
PULSING |
byte | Pulsing animation flag |
HILIGHTSELECTED Struct:
| Field | Type | Description |
|---|---|---|
CORNER |
ResRef | Corner texture for highlight+selected state |
EDGE |
ResRef | edge texture for highlight+selected state |
FILL |
ResRef | Fill texture for highlight+selected state |
FILLSTYLE |
int32 | Fill style |
DIMENSION |
int32 | Border thickness |
INNEROFFSET |
int32 | Inner padding X-axis |
INNEROFFSETY |
int32 | Inner padding Y-axis (optional) |
COLOR |
vector | Combined state color modulation |
PULSING |
byte | Pulsing animation flag |
State Priority:
- HILIGHTSELECTED: When control is both highlighted (hovered) and selected
- HILIGHT: When control is highlighted (hovered) but not selected
- SELECTED: When control is selected but not highlighted
- BORDER: Default appearance
Control-Specific fields
ListBox (type 11):
| Field | Type | Description |
|---|---|---|
PROTOITEM |
Struct | Template for list item appearance |
SCROLLBAR |
Struct | Embedded scrollbar control |
PADDING |
int32 | Spacing between items (pixels) |
MAXVALUE |
int32 | Maximum scroll value (total items - visible items) |
CURVALUE |
int32 | Current scroll position |
LOOPING |
byte | Loop scrolling (0=no, 1=yes) |
LEFTSCROLLBAR |
byte | Scrollbar on left side (0=right, 1=left) |
ListBox Behavior:
- PROTOITEM: Defines appearance template for each list item
- SCROLLBAR: Embedded scrollbar for navigating long lists
- PADDING: Vertical spacing between items
- MAXVALUE: Maximum scroll offset (when all items visible, MAXVALUE=0)
- LOOPING: When enabled, scrolling past end wraps to beginning
- LEFTSCROLLBAR: positions scrollbar on left instead of right
PROTOITEM Struct (for ListBox):
| Field | Type | Description |
|---|---|---|
CONTROLTYPE |
int32 | Always 4 (ProtoItem) |
EXTENT |
Struct | Item size and position |
BORDER |
Struct | Item border appearance |
HILIGHT |
Struct | Item highlight on hover |
HILIGHTSELECTED |
Struct | Item highlight when selected |
SELECTED |
Struct | Item appearance when selected |
TEXT |
Struct | Item text properties |
ISSELECTED |
byte | Default selected state |
ScrollBar (type 9):
| Field | Type | Description |
|---|---|---|
DIR |
Struct | Direction arrow buttons appearance |
THUMB |
Struct | Draggable thumb appearance |
MAXVALUE |
int32 | Maximum scroll value |
VISIBLEVALUE |
int32 | Number of visible items in viewport |
CURVALUE |
int32 | Current scroll position |
DRAWMODE |
byte | Drawing mode (0=normal, other values unused) |
ScrollBar Behavior:
- MAXVALUE: Total scrollable range
- VISIBLEVALUE: size of visible area (determines thumb size)
- CURVALUE: Current scroll offset (0 to MAXVALUE)
- Thumb size = (VISIBLEVALUE / MAXVALUE) × track length
DIR Struct (ScrollBar Direction Buttons):
| Field | Type | Description |
|---|---|---|
IMAGE |
ResRef | Arrow button texture |
ALIGNMENT |
int32 | Image alignment (typically 18=center) |
DRAWSTYLE |
int32 | Drawing style (unused) |
FLIPSTYLE |
int32 | Flip/rotation style (unused) |
ROTATE |
float | rotation angle (unused) |
THUMB Struct (ScrollBar Thumb):
| Field | Type | Description |
|---|---|---|
IMAGE |
ResRef | Thumb texture |
ALIGNMENT |
int32 | Image alignment (typically 18=center) |
DRAWSTYLE |
int32 | Drawing style (unused) |
FLIPSTYLE |
int32 | Flip/rotation style (unused) |
ROTATE |
float | rotation angle (unused) |
ProgressBar (type 10):
| Field | Type | Description |
|---|---|---|
PROGRESS |
Struct | Progress fill appearance |
CURVALUE |
int32 | Current progress value (0-100) |
MAXVALUE |
int32 | Maximum value (typically 100) |
STARTFROMLEFT |
byte | Fill direction (0=right, 1=left) |
ProgressBar Behavior:
- CURVALUE: Current progress (0-100, or 0-MAXVALUE)
- STARTFROMLEFT: When 1, fills left-to-right; when 0, fills right-to-left
- Progress = (CURVALUE / MAXVALUE) × width
PROGRESS Struct:
| Field | Type | Description |
|---|---|---|
CORNER |
ResRef | Corner texture for progress fill |
EDGE |
ResRef | edge texture for progress fill |
FILL |
ResRef | Fill texture for progress bar |
FILLSTYLE |
int32 | Fill rendering style |
DIMENSION |
int32 | Border thickness |
INNEROFFSET |
int32 | Inner padding X-axis |
INNEROFFSETY |
int32 | Inner padding Y-axis (optional) |
COLOR |
vector | Progress fill color modulation |
PULSING |
byte | Pulsing animation flag |
CheckBox (type 7):
| Field | Type | Description |
|---|---|---|
SELECTED |
Struct | Appearance when checked |
HILIGHTSELECTED |
Struct | Appearance when checked and hovered |
ISSELECTED |
byte | Default checked state (0=unchecked, 1=checked) |
CheckBox Behavior:
- Toggles between checked/unchecked on click
- ISSELECTED: Initial state
- SELECTED: Visual appearance when checked
- HILIGHTSELECTED: Visual appearance when checked and hovered
Slider (type 8):
| Field | Type | Description |
|---|---|---|
THUMB |
Struct | Slider thumb appearance |
CURVALUE |
int32 | Current slider value |
MAXVALUE |
int32 | Maximum slider value |
DIRECTION |
int32 | Orientation (0=horizontal, 1=vertical) |
Slider Behavior:
- CURVALUE: Current position (0 to MAXVALUE)
- MAXVALUE: Maximum value (typically 100)
- DIRECTION: 0=horizontal (left-right), 1=vertical (top-bottom)
- Thumb position = (CURVALUE / MAXVALUE) × track length
Slider THUMB Struct:
| Field | Type | Description |
|---|---|---|
IMAGE |
ResRef | Thumb texture |
ALIGNMENT |
int32 | Image alignment |
DRAWSTYLE |
int32 | Drawing style (unused) |
FLIPSTYLE |
int32 | Flip/rotation style (unused) |
ROTATE |
float | rotation angle (unused) |
Button (type 6):
| Field | Type | Description |
|---|---|---|
HILIGHT |
Struct | Hover state appearance |
MOVETO |
Struct | D-pad navigation targets |
TEXT |
Struct | Button label text |
Button Behavior:
- Clickable control with text label
- HILIGHT: Shown on mouse hover; hover event plays hardcoded sound
gui_actscroll[xoreosbutton.cppL124] - Click event plays hardcoded sound
gui_actuse[xoreosbutton.cppL148] - TEXT: Button label (can use StrRef for localization)
- MOVETO: Keyboard/D-pad navigation
Label (type 5):
| Field | Type | Description |
|---|---|---|
TEXT |
Struct | Text display properties |
Label Behavior:
- Static text display (non-interactive)
- TEXT: Text content, font, alignment, color
- Used for UI labels, descriptions, headers
Panel (type 2):
| Field | Type | Description |
|---|---|---|
CONTROLS |
List | Child controls list |
BORDER |
Struct | Panel border (optional background) |
COLOR |
vector | Panel color modulation |
ALPHA |
float | Panel transparency |
Panel Behavior:
- Container for child controls
- CONTROLS: List of child controls (any type)
- BORDER: Optional background/border
- Child controls positioned relative to panel
ProtoItem (type 4):
| Field | Type | Description |
|---|---|---|
TEXT |
Struct | Item label text |
BORDER |
Struct | Item border appearance |
HILIGHT |
Struct | Item highlight on hover |
HILIGHTSELECTED |
Struct | Item highlight when selected |
SELECTED |
Struct | Item appearance when selected |
ISSELECTED |
byte | Default selected state |
ProtoItem Behavior:
- Template for list items (used by ListBox)
- Defines appearance of individual list entries
- ISSELECTED: Initial selection state
- States: Normal, Highlighted, Selected, Highlighted+Selected
Implementation Notes
Control Hierarchy:
- GUI root contains
CONTROLSlist of top-level controls - Controls can have child controls via
CONTROLSlist - Child controls positioned relative to parent's EXTENT
- Parent visibility affects children (hidden parent hides children)
- Z-order: Children render above parents, and later controls render above earlier ones (rendering order is determined by control list order) (reone
gui.cppL80-92, reonecontrol.cppL192-194).
Positioning System:
- Base resolution: 640x480 pixels (engine default, scaled for higher resolutions) (reone
gui.hL38-39). - coordinates are pixel-based, engine scales for higher resolutions
- EXTENT.LEFT/TOP: position relative to parent (or screen for root)
- Negative coordinates allowed (positioning outside parent bounds)
- Root control EXTENT defines GUI bounds
color System:
- color (Vector3): RGB color modulation (0.0-1.0 range)
- ALPHA (float): Transparency (0.0=transparent, 1.0=opaque)
- colors multiply with textures (white=full color, black=no color)
- KotOR 1 default text color: RGB(0.0, 0.658824, 0.980392) — cyan [KotOR.js
GUIControl.tsL188] - KotOR 2 default text color: RGB(0.102, 0.698, 0.549) — teal [KotOR.js
GUIControl.tsL192] - KotOR 1 default highlight color: RGB(1.0, 1.0, 0.0) — yellow [KotOR.js
GUIControl.tsL189] - KotOR 2 default highlight color: RGB(0.8, 0.8, 0.698) [KotOR.js
GUIControl.tsL193]
Border Rendering:
- Border consists of 9 pieces: 4 corners, 4 edges, 1 fill
- CORNER textures: Top-left, top-right, bottom-left, bottom-right
- edge textures: Top, right, bottom, left (tiled along length)
- FILL texture: Center area (scaled or tiled based on FILLSTYLE)
- DIMENSION: Thickness of border edges in pixels
- INNEROFFSET: Padding between border and content
Text Rendering:
- Fonts are texture-based (TPC or TGA files with character grid)
- Each character has fixed width/height in font texture
- If STRREF is a valid index, the engine resolves it via TLK; if STRREF is absent/
0xFFFFFFFF, the direct TEXT string is used [xoreoswidget.cppcreateTextL544, PyKotorgui.pyL362] - StrRef references dialog.tlk for localized strings
- ALIGNMENT uses bitfield: horizontal (1=left, 2=center, 3=right) + vertical (0=top, 16=center, 32=bottom) [
gui.pyGUIAlignment] - Text color modulates font texture
State Management:
- Normal: BORDER struct defines appearance
- Hover: HILIGHT struct overlays/replaces BORDER
- Selected: SELECTED struct defines appearance (CheckBox, ListBox items)
- Hover+Selected: HILIGHTSELECTED struct (highest priority)
Control IDs:
- ID field: Unique control identifier read by PyKotor as
IDint32 [gui.pyconstruct_control]; read by reone viagetTag/getId[reonecontrol.cppL48] - TAG field: String identifier; used by reone for parent lookup via
Obj_Parent[reonecontrol.cppL52]
Navigation:
- MOVETO struct defines D-pad/keyboard navigation
- value is Control ID of target control
- -1 or 0 indicates no navigation in that direction
- Essential for controller/keyboard-only gameplay
ScrollBar Integration:
- ListBox controls can embed SCROLLBAR struct [xoreos
listbox.cppL70, PyKotorgui.py] SCROLLBAR.MAXVALUEdefault 99;SCROLLBAR.VISIBLEVALUEdefault 1 [PyKotorgui.pyconstruct_control]SCROLLBAR.CURVALUE= current scroll offset- Thumb size proportional to viewport:
(trackLength - 2 × arrowHeight) × (visibleValue / maxValue)[xoreosscrollbar.cpp] LEFTSCROLLBAR: positions scrollbar on left side [xoreoslistbox.cppL71]
Pulsing animation:
- PULSING flag in BORDER, TEXT, HILIGHT, SELECTED structs [
gui.pyGUIBorder.pulsing L65] - When enabled, control pulses (fades in/out)
- Used for attention-grabbing effects
texture formats:
- GUI textures use TPC or TGA format; fields CORNER/EDGE/FILL are ResRef strings
- xoreos HILIGHT struct reads only the
FILLfield (no CORNER/EDGE for highlights) [xoreoswidget.cppL580] - Font textures contain character glyphs; each glyph rendered at fixed grid position [xoreos
GUIFont.ts]
KotOR-Specific Notes:
- GUIs are loaded from
.guifiles (GFF format); entry functionconstruct_gui[PyKotorgui.pyL353] - Base resolution 640×480; implementations scale to screen by aspect or center offset [reone
gui.hL37-38, reonegui.cppscaling L119-124] - Controls located by
TAGstring [reonecontrol.cppL52] orIDinteger [PyKotorgui.py]
See also
- GFF-File-Format -- Generic format underlying GUI
- GFF Creature and Dialogue -- UTC and DLG types
- GFF Items and Economy -- UTI, UTM, JRL, FAC types
- GFF Module and Area -- ARE, GIT, IFO types
- TPC File Format — textures used by GUI controls
- TLK File Format - String references for GUI text
- NCS File Format - Scripts that drive GUI behavior