Skip to content

FairyGUI Binary Package Format

This document describes only the protocol structure of FairyGUI published binary packages. It follows the formal V7 protocol and does not expand into a multi-version manual or describe project-specific internal storage.

Contents

SectionLink
Overall layoutView
File headerView
CompressionView
Index tableView
String tableView
Block 0: DependenciesView
Block 1: Package ItemsView
Block 2: SpritesView
Block 3: Pixel Hit TestView
Component decodingView
Component / Decode targetView
Component / Decode entryView
Component / Top-level block layoutView
Component / Top-level block detailsView
Component / Child decodingView
Component / Child Block 8View
Component / Extension types and afterAdd dataView
Component / Structured-object boundaryView
Component / Runtime phase mappingView
Component / Decode resultView
Version contractView

Overall layout

A binary package consists of a fixed header followed by a data region. The header is always uncompressed. When compressed=true, the data region after the header uses raw deflate.

text
[Header]
  magic
  version
  compressed
  packageId
  packageName
  reserved(20 bytes)

[Body]
  index table
  block 0: dependencies
  block 1: package items
  block 2: sprites
  block 3: pixel hit test
  block 4: string table
  block 5: long string patches

File header

FieldProtocol
magicFixed to FGUI_MAGIC, the uint32 value for "FGUI"
versionFixed to 7 by the V7 protocol
compressedbool indicating whether the data region after the header uses raw deflate
packageIdPackage ID
packageNamePackage-name string
reservedExactly 20 reserved bytes

Notes:

  • This document defines only the V7 protocol.
  • packageName is the package-name field, not the published output filename.

Compression

ScenarioProtocol
compressed=falseWrites the uncompressed data region immediately after the header
compressed=trueWrites the raw-deflate-compressed data region after the header

Index table

The data region begins with an index table locating the following six blocks.

FieldProtocol
segCount6
useShortfalse
Offset typeuint32

Offsets appear in this order:

BlockMeaning
0dependencies
1package items
2sprites
3pixel hit test
4string table
5long string patches

String table

Length-prefixed strings, sub-buffers and block offsets must remain within their containing buffer. A string-table index must identify an existing entry or a protocol-defined null/empty sentinel; an out-of-range index is not an empty string.

Block 4

ContentProtocol
String countint32
Normal stringWritten directly as UTFString
Long stringAn empty placeholder is written in block 4, with content stored in block 5

Block 5

ContentProtocol
Patch countint32
Each patchindex + byteLength + raw UTF-8 bytes

A block 5 patch replaces the placeholder at the same string-table index in block 4.

The writer validates protocol uint8 / int8 / uint16 / int16 / uint32 / int32 values, UTFString byte lengths, and string-table indexes before writing. Values wider than their fields are rejected instead of being silently truncated by JavaScript DataView; string-table indexes never consume the reserved empty/null slots 65533 / 65534.

Block 0: Dependencies

FieldProtocol
depCntint16
DependencyEach entry writes id and name
Conditional fieldsThe branch segment writes branchCount:int16, followed by branch names in order

This branch-name list belongs to the current package. Its order defines the slot meaning of every branchItemIds list for that package in Block 1. Different packages may use different branch subsets and orders; the project-level branch list cannot replace it.

Block 1: Package Items

This block stores package entries. Every entry has a common header followed by its type-specific data segment.

Recorded item types

Type codeItem typeProtocol content
0Imageid, name, path, dimensions, scaleOption, scale9Grid, tileGridIndice, smoothing
1MovieClipCommon fields plus frame-data block
2SoundCommon fields plus sound filename
3ComponentCommon fields plus extension type code and component binary data
4AtlasAtlas-entry id, file, and dimensions
5FontCommon fields plus glyph-data block
7MiscUnclassified item
8UnknownUnmodeled package item type code
9SpineCommon fields plus resource filename, skeletonAnchor.x, and skeletonAnchor.y
10DragonBonesCommon fields plus resource filename, skeletonAnchor.x, and skeletonAnchor.y

Common header fields

Every package item writes this common header before its type-specific segment:

FieldProtocol
typeuint8 item type code
idResource ID
nameResource name
pathResource path
fileFilename or relative path loaded by the runtime after publishing
exportedWhether the resource is exported
widthResource width
heightResource height

The Font glyph-data block stores its UTF-16 code unit (charId) as uint16, covering the complete BMP range. Image references and glyph metrics then use their respective string-table indices and int32 fields.

Bitmap glyph image references must resolve in the same package's resource and sprite tables. A whole-font texture is addressed by the font ID in the sprite table. After branch merging, glyph image IDs refer to merged resources. Imported TTF/TTC/OTF fonts use their engine font name in text font fields and are not encoded as bitmap Font resources.

Spine / DragoneBones item segment

Spine and DragoneBones append a skeleton anchor after the common header:

FieldProtocol
skeletonAnchor.xfloat32
skeletonAnchor.yfloat32

Notes:

  • Project resource fields such as require and atlasNames are not written directly into the package-item segment.
  • The runtime locates and aligns a skeleton resource through file and skeletonAnchor.

Publish semantics of file

file stores the resource location in published output, not the original filename under the project resource directory:

Resource typeMeaning of file
Atlas / Sound / Misc / SwfPublished auxiliary-resource filename; the runtime adds the package asset prefix required by the target
Spine / DragoneBonesPublished primary skeleton-resource filename, which the runtime uses to load the corresponding resource

For Sound / Misc / Swf, file is the published item ID plus the source extension. Unity additionally appends .txt to .atlas. For example, hero.json with item ID biss7 is stored as biss7.json; its physical auxiliary file carries the package publish-name prefix expected by the runtime. Swf uses item type code 6.

Current Unity naming for Spine primary and dependent resources is:

Project resource filePublished result
*.skel*.skel.bytes
*.atlas (Misc dependency)<item-id>.atlas.txt
*.pngOriginal filename retained

Non-Unity primary skeleton files retain the filename required by their target; dependencies published as Misc still use <item-id><source-extension>.

When publish settings enable separate branch atlases, an atlas item's file contains a branch suffix, such as atlas0_dev.png. The main atlas remains atlas0.png.

The DragoneBones primary file retains the filename required by its target. Misc dependencies use their published item IDs, while image dependencies retain their published image names.

Conditional trailing fields

The end of an item contains conditional data:

FieldProtocol
branch nameBranch containing the current item; a main-branch item writes null
branchCountNumber of branch mappings. When the package has a branch table, a main item writes branch-variant item IDs in package-level branch order.
highResCountNumber of high-resolution variant slots, followed by package item IDs in @2x, @3x, @4x order

Notes:

  • When a package-level branch table exists, a main item's branchCount is the number of branch slots written.
  • A branch variant item writes only its branch name and does not recursively contain another branchCount mapping.
  • The high-resolution list references only image or movieclip resources already published as package items. Publishing does not enlarge source bitmaps.
  • If an intermediate scale is missing while a later scale exists, the missing slot is null; missing trailing slots are omitted.
  • In merge active branch into main mode, branch replacement is already complete. Package-level branchCount is 0, and item branch name and branchCount are empty.
  • When branches are retained and branch atlases are separate, a branch may use independent atlas items. Current editor samples use 100 + pageIndex as the branch atlas index.

Block 2: Sprites

FieldProtocol
Sprite countuint16
Base fieldsitemId, atlasId, x, y, w, h, rotated
Conditional fieldsoffsetX, offsetY, originalWidth, originalHeight

This block describes each resource's trimmed atlas rectangle and original dimensions. The trailing segment is present when offsets are non-zero, the sprite is rotated or zero-sized direct output, or the original dimensions differ from the trimmed rectangle. A sprite trimmed only on its right or bottom edge therefore retains originalWidth / originalHeight even with zero offsets.

Block 3: Pixel Hit Test

FieldProtocol
Countint16
Each entryitemId, deprecated offset, pixelWidth, scaleDenominator, and bitmask length/data

This block describes pixel-level hit-test data for image resources.

Component decoding

Decode target

The data region of a Component item is an independent component buffer rather than an ordinary resource-field set. It expands according to the component protocol into semantic structures including:

Semantic objectDecoded result
ComponentHeader, relations, advanced properties, extension definition, scroll pane, transitions
Child nodesbeforeAdd / afterAdd / gears / relations / type-specific data
ControllerName, pages, home-page type, actions container
TransitionHeader, items, tweens, values, paths, labels, targets
GearController binding, pages, state values, tween conditions
ScrollPane / List / TreeScroll configuration, list layout, tree settings, resource references, and controller references

Decode entry

When the package item type is Component, its data region contains these steps:

StepProtocol action
1Read extension type
2Read the component binary buffer
3Interpret the buffer through its component-level index table
4Decode the component in top-level block order
5Decode every display-list child through the child's own index table

Top-level block layout

A component has eight top-level blocks in a fixed order:

BlockDecode target
0Component header: dimensions, restricted size, pivot, margin, overflow, clipSoftness
1Controllers: controller list, pages, action containers
2Display list: child list, with nested per-child decoding
3Component-level relations
4Advanced properties: customData, opaque, mask, hitTest, stage sounds
5Transitions
6Extension definition: Button / Label / ComboBox / ProgressBar / Slider / ScrollBar
7ScrollPane: present only for overflow=scroll

Required decode order:

  • First read blockCount and useShort from the component index-table header.
  • Then read the eight block offsets in order.
  • An offset of 0 for block 6 or 7 means that block is absent.

Top-level block details

Block 0: Component header

Field groupContent
DimensionssourceWidth, sourceHeight
Restricted sizeminWidth, maxWidth, minHeight, maxHeight
PivotpivotX, pivotY, pivotAsAnchor
Margintop, bottom, left, right
OverflowVisible / Hidden / Scroll
Clip softnessx, y

The component-header and child pivot presence flag is set when either coordinate is nonzero or pivotAsAnchor=true; (0,0,true) differs from an absent pivot.

Block 1: Controllers

Every controller has its own three-block index table:

Sub-blockContent
0name, autoRadioGroupDepth
1pages as ID and name, plus homePageType
2actions container and action payload

The formal homePageType:uint8 values and their trailing payloads are:

ValueMeaningTrailing payload
0First page (default)None
1Specific page (specific)Page index as int16
2Match branch name (branch)None
3Match variable value (variable)Project-variable key string

Controller alias and exported are editor metadata in project XML and are not written into this runtime Controller block.

The actions block begins with actionCount:int16. Each action then starts with chunkSize:int16, followed by fields in this fixed order:

FieldMeaning
actionType:uint80 = PlayTransition, 1 = ChangePage
fromPageCount:int16 + fromPage[]Source-page ID filters
toPageCount:int16 + toPage[]Target-page ID filters
Conditional payloadFurther fields selected by actionType

Conditional payloads:

actionTypePayload
PlayTransitiontransitionName, playTimes:int32, delay:float32, stopOnExit:bool
ChangePageobjectId, controllerName, targetPage

Block 2: Display list

This block stores the child list:

StepProtocol action
1Read child count
2Read each child's dataLen
3Read the child's index table
4Select the child type by object type
5Decode common fields, type-specific fields, relations, gears, and afterAdd data in child-block order

Block 3: Component-level relations

ContentDescription
TargetResolved by child index first
Relation pairsEach target has multiple relation-type and usePercent pairs

Component-root and child relation targets use indexes into the same published child list. Ordinary Groups (advanced=false) occupy no slot; advanced Groups retain their slots. A parent target uses -1.

Block 4: Advanced properties

FieldDescription
customDataComponent custom data
opaqueWhether the component is opaque
mask / reversedMaskReferences a child by display-list index
hitTestChild-index mode or external hit-test-resource mode
addedToStageSound / removedFromStageSoundConditional fields

Block 5: Transitions

ContentDescription
Transition headername, options, autoPlay, autoPlayTimes, autoPlayDelay
Item headeractionType, time, target, label, tween
Tween blockduration, easeType, repeat, yoyo, endLabel
Value blockvalue / startValue / endValue
Path blockpath, custom-ease path

Block 6: Extension definition

Extension typeContent
Buttonmode, sound, soundVolumeScale, downEffect, downEffectValue
LabelNo additional definition block
ComboBoxdropdown
ProgressBartitleType, reverse
SlidertitleType, reverse, wholeNumbers, changeOnClick
ScrollBarfixedGripSize

Block 7: ScrollPane

Present only when component overflow=scroll:

Field groupContent
Scroll basescrollType, scrollBarFlags
MarginscrollBarMargin
Resource referencesvtScrollBarRes, hzScrollBarRes, headerRes, footerRes

Child decoding

Common child structure

Each child has an independent index table, with a block count determined by object type:

Child typeBlock count
Ordinary child7
GList9
Tree10

Notes:

  • Tree is not an independent outer resource-entry type.
  • The current formal model uses GTree, while Project XML follows the editor form <list treeView="true">.

Object type mapping

Object type indexComponent object type
0GImage
1GMovieClip
3GGraph
4GLoader
5GGroup
6GTextField
7GRichTextField
8GTextInput
9GComponent
10GList
11GLabel
12GButton
13GComboBox
14GProgressBar
15GSlider
16GScrollBar
17GTree
18GLoader3D

Child block decode order

BlockContent
0beforeAdd: object type, src, pkgId, id, name, xy, size, restricted size, scale, skew, pivot, alpha, rotation, visible, touchable, grayed, blend, color filter, customData
1Common afterAdd segment: tooltips, group
2Gears
3Relations
4GComponent / GList page controller or GTextInput type-specific segment
5Child-type-specific extension
6afterAdd text/icon/extension-instance data
7GList scroll pane
8GList static list items
9Tree settings

Child Block 4

TypeContent
GComponent, GList, GButton, GLabel, GComboBox, GProgressBar, GSlider, GScrollBarPage controller and controller overrides; V2+ then stores ordered property overrides as target / propertyId / value
GTextInputInput-field-specific settings
Other typesOffset is 0; the block is absent

Child Block 5: Type-specific extensions

TypeMain fields
GImagecolor, flip, fillMethod, fillOrigin, fillClockwise, fillAmount
GTextField / GRichTextField / GTextInputfont, fontSize, color, align, vAlign, leading, letterSpacing, ubb, autoSize, underline, italic, bold, singleLine, stroke, shadow, strikethrough, faceDilate, outlineSoftness, underlaySoftness
GGraphgraphType, lineSize, lineColor, fillColor, cornerRadius, points, sides, startAngle, distances
GGrouplayout, lineGap, columnGap, excludeInvisibles, autoSizeDisabled, mainGridIndex
GLoaderurl, align, vAlign, fill, shrinkOnly, autoSize, playing, frame, color, fillMethod, useResize
GLoader3Durl, align, vAlign, fill, shrinkOnly, autoSize, animationName, skinName, playing, frame, loop, color
GMovieClipcolor, frame, playing
GListlayout, selectionMode, align, vAlign, lineGap, columnGap, lineCount, columnCount, autoResizeItem, childrenRenderOrder, apexIndex, margin, overflow, clipSoftness, scrollItemToViewOnClick, foldInvisibleItems

Extension types and afterAdd data

Block 6 restores data written during the afterAdd phase:

TypeContent
GTextField / GRichTextField / GTextInputtext
GButtontitle, selectedTitle, icon, selectedIcon, titleColor, titleFontSize, relatedController, relatedPageId, sound, soundVolume, selected
GLabeltitle, icon, titleColor, titleFontSize, input-setting placeholder, sound, soundVolumeScale
GComboBoxitems, values, icons, title, icon, titleColor, visibleItemCount, popupDirection, selectionController, sound, soundVolumeScale
GProgressBarvalue, max, min, sound, soundVolumeScale
GSlidervalue, max, min
GListselectionController
GComponent Button extension instancetitle, selectedTitle, icon, selectedIcon, titleColor, titleFontSize, relatedController, relatedPageId, sound, soundVolumeScale, selected
GComponent Label extension instancetitle, icon, titleColor, titleFontSize, input settings, sound, soundVolumeScale
GComponent ComboBox extension instanceitems, title, icon, titleColor, visibleItemCount, popupDirection, selectionController, sound, soundVolumeScale
GComponent ProgressBar extension instancevalue, max, min, sound, soundVolumeScale
Other extension-instance dataSlider / ScrollBar instance data selected by the InstanceExtType branch

Child Block 7: List ScrollPane

GList and GTree share Block 7. It stores scrollType, scrollBarDisplay (0 default, 1 visible, 2 auto, 3 hidden), scrollBarFlags, scrollbar margins, and scrollbar/pull-to-refresh resource references in that order.

Child Block 8: Static List Items

GList and GTree share Block 8. The block first writes the default item resource and item count, then stores every static item as a length-prefixed chunk:

OrderFieldEncoding and semantics
1defaultItemString-table reference
2itemCountInt16
3chunkSizeOne Int16 per item, giving the byte length of item data after this length field
4urlString-table reference
5isFolderPresent only for GTree; Bool
6levelPresent only for GTree; UInt8; negative values clamp to 0 before writing
7title, selectedTitleNullable string references
8icon, selectedIcon, nameNullable string-table references
9controllerOverrideCountInt16
10Controller overridesRepeated controllerOverrideCount times; each entry writes (controllerName, selectedPageId) as two string-table references
11propertyOverrideCountInt16 in V2+
12Property overridesRepeated propertyOverrideCount times; each entry writes target, propertyId: Int16, and value

The static-item controllers field uses comma-separated pairs: controllerName,selectedPageId,.... Encoding writes one controller override per pair. An empty controller name does not create an override, and a missing selected-page ID is written as an empty string. Decoding reconstructs the paired string in the same order. Property overrides round-trip in model order.

A Tree item's isFolder has no null representation in the binary, so encoding resolves it as follows:

  • Explicit true or false is written unchanged.
  • When null or omitted, it is true only if the next item's level is greater than the current item's level.
  • It is false when the next item is at the same or a shallower level, or when the current item is last.

This preserves hierarchy semantics for leaf nodes without icons or URLs. Icons and resource URLs do not participate in folder inference.

Structured-object decoding boundary

Controller

ContentRequirement
Namename
PagesControllerPage.id, ControllerPage.name
Home-page datahomePageType and selected-page semantics
ActionsfromPage and toPage filters plus the payload for PlayTransition or ChangePage

Gear

ContentRequirement
Gear typeMatches the gear type on the child
Controller bindingResolves the controller index to a controller reference
PagesPage-ID list
Values/defaultState structure determined by gear type
TweenEase, duration, delay, and custom-ease path
Extended stateConditional fields such as GearXY percentages and GearAnimation extended state

Each child has one slot per Gear type, regardless of its controller binding; Display and Display2 are separate types. The XY percentage extension stores floating-point px/py coordinates relative to the parent size (0.5 means 50%). Size scales and Look alpha may be 0.

XY, Size, Look, Color, Animation, FontSize, Text, and Icon store the presence of a default state in a separate Boolean. Without that payload, the runtime retains the default captured from the owner's initial properties. Unconfigured pages return to that state instead of a fixed zero size, white color, or font size.

For Text/Icon, empty strings, -, and strings containing | are complete state values. A null page carries no state payload. A separate Boolean records default-value presence, distinguishing an absent default override from an explicit empty string.

Transition

ContentRequirement
Item headeractionType, time, target, label
Tweenduration, easeType, repeat, yoyo, endLabel
Valuevalue / startValue / endValue
Pathpath, custom-ease path

Scale 0 is a valid scale. Sound volume 0 means silence, and a nested Transition play count of 0 means stop; these values are not replaced by defaults.

ScrollPane

ContentRequirement
Component scroll panescrollType, scrollBarFlags, scrollBarMargin, vt/hz scrollBarRes, headerRes, footerRes
List scroll paneThe list's own scroll-pane data
Tree/list additional flagsscrollItemToViewOnClick, foldInvisibleItems, and tree settings

Relations

ContentRequirement
Child/component relationsRelation type and usePercent
Target resolutionResolve by child index first, then handle numeric indices

Runtime phase mapping

PhaseCorresponding data
constructFromResource2Component top-level blocks 0-7 and child-list assembly
setup_beforeAddChild blocks 0 and 5 plus list/tree extension blocks
setup_afterAddChild blocks 1, 4, and 6 plus extension-instance data
ScrollPane / Extension definitionComponent blocks 6 and 7 plus extra list blocks

Decode result

After component decoding, the result should directly provide:

DimensionResult
StructureTop-level component structure, child list, controllers, transitions, gears, relations, and scroll pane
SemanticsDirect semantic field access rather than raw byte blocks
Re-encodingComponent data can be encoded again from the structured result

Version contract

TopicDescription
Formal protocolThis document defines and describes V7 only
Standard written valueThe package-header version is always 7 when encoding according to this document
Conditional fieldsA conditional field appears only under its stated condition; it does not indicate a parallel protocol version

MIT Licensed