PContent format reference¶
Status: implemented baseline for supported package, aggregate, material, and image traits.
Container¶
.pcontent is a ZIP archive. Supported packages appear in three forms:
a renderable entity with one
.pmob, embedded images, andproperties.json;a material package with one material-only PMob; or
a properties-only aggregate whose geometry comes from referenced child specifications.
The observed properties.json member can use the .NET BinaryWriter string
representation: a 7-bit encoded UTF-8 byte length followed by JSON bytes. The
reader also accepts plain UTF-8 JSON for independently produced packages.
Properties and referenced packages¶
The properties object can describe logical dimensions, drawing dimensions, limits, models, components, open services, aggregate children, lighting, and material choices.
An aggregate can contain a list of specification UUIDs and expressions for dimensions, position, rotation, and visibility. Mooblender selects the declared default, resolves its public detail record, and recursively loads PContent with depth, entity, and cycle limits. Repeated specification IDs reuse parsed package data and mesh datablocks.
The supported expression grammar includes:
$PW$,$PD$,$PH$for parent width, depth, and height;$W$,$D$,$H$for child dimensions;equivalent long names such as
$PARENTWIDTH$and$WIDTH$;arithmetic and numeric comparisons;
Boolean operators;
C-style ternaries inside
@(...); andmodel-information tokens such as
@Component(TYPE)@.
The evaluator implements only this bounded grammar. It does not execute Python or arbitrary source text. A supported false visibility expression omits the aggregate; an unresolved unfamiliar token retains geometry rather than silently removing alternatives.
Dimensions and placement¶
Dimension, DrawingDimension, and measured PMob geometry are separate:
Dimensionsupplies logical/default values and child-expression variables.DrawingDimensiondescribes the authored drawing coordinate extent.measured geometry is calculated after primitive transforms.
GeometryBoundingBoxis a fallback when renderable geometry is absent.
At a root, each axis prefers drawing dimension, then logical dimension, then measured geometry. A child target derives from aggregate expressions and its own defaults. Geometry resizing applies only to that child’s PMob geometry; nested aggregate positions already use the resized coordinate system and must not receive the scale a second time.
An aggregate Normal orients local positive Z. A normal does not determine
roll, so Mooblender projects global negative Z into the attachment plane as a
stable local X reference and applies Rotation around the normal. Opposing side
normals therefore keep a consistent vertical direction. Inversion stays on the
aggregate placement so it affects geometry and descendants together.
Editable and fixed dimensions¶
InsertDimension.Min and InsertDimension.Max define editable axis ranges.
API records use X/Y/Z while domain names can use Width/Depth/Height. An axis is
exposed as a Blender distance input only when its range varies and the current
default lies inside that range.
An aggregate marked Constant: true fixes its child even if that reusable child
publishes broad insertion limits. Fixed axes and constant children do not create
misleading controls. Controls belong to concrete package instances, so changing
one nested part does not resize a sibling instance.
Some packages flatten fixed hardware into the same PMob as an editable panel. When component metadata marks that region non-editable, Mooblender preserves the nearest boundary and hardware span while stretching the remaining panel region. This behavior is a package fallback; separate constant aggregates remain the preferred representation.
Doors, drawers, options, and reversal¶
OpenServices.AggregatePath alternates aggregate-container and selected-option
indices. A door supplies a pivot and maximum angle; a drawer supplies maximum
travel. Each valid movable instance receives its own 0–1 Geometry Nodes value,
using localized component names when available.
Controls are created lazily. A package without a valid movement service receives no inactive door or drawer input.
Aggregates marked Concurrent or Coupled can become default-enabled options
unless they are constant or always visible. Repeated coupled components with the
same description share one switch. The CANMIRROR attribute adds a Reverse
control that reflects the complete X footprint around its reported limits.
Face-winding parity is corrected for component inversion and whole-object
reversal so visible normals remain outward.
Finishes¶
Models groups map PMob layer IDs to material specification UUIDs.
Multi-option groups become named Finish menus. The first option is the
default, including single-option groups and meshes with no local material ID.
Selections are scoped by package identity and layer ID because parent and child packages can reuse layer names while having independent finishes. A model-wide group is labeled Main; available component descriptions are retained.
Safety policy¶
The reader operates in memory and does not extract archive paths. It rejects:
absolute paths and parent traversal;
excessive member counts or unpacked size;
suspicious compression ratios;
packages containing neither PMob nor properties;
ambiguous multiple PMob members; and
unsafe or unsupported embedded-image names.
Images are loaded through a private temporary file, packed into the Blender datablock, and the temporary file is removed immediately.