Skip to content
Shapemetry

@huukhanhnguyen/model / core/ModelScope

core/ModelScope

ModelScope

Runtime scope holder for a parametric model. Carries the node graph, unit configuration, static asset lanes, and the cross-lane resolver hooks (Model.ts wires them, avoiding a circular import) every isolated scope (components[]/textures[]) reaches through.

Extends

Constructors

Constructor

new ModelScope(name?): ModelScope

Parameters

name?

string = "Model"

Returns

ModelScope

Overrides

BaseObject.constructor

animations

animations: Chain[] = []

Animation chains (track nodes) — evaluateAnimations folds to clips.

annotationStyles

annotationStyles: Operation[] = []

Annotation styles lane — annotationStyle operation nodes (arrow and extension-line geometry, measurement formatting). Resolved via collectAnnotationStyles() into AnnotationStyle records consumed by-name from every dimension/leader node. Kept SEPARATE from textStyles for DXF's reason — see schema/lanes.ts.

assets?

optional assets?: Store

attributes

attributes: Record<string, unknown> = {}

Inherited from

BaseObject.attributes

blockKeys

blockKeys: Set<string>

Authored BlockNode keys — evaluate wraps each child as its own object.

cameras

cameras: CameraNode[] = []

Named camera poses (camera method). A view3d head may reference by key. NOT product: never enters the data stream. A LIGHT is an ordinary object whose data is LightData, not a lane node at all; axes and a floor grid are a VIEWER setting, not a lane either (the helpers[] lane was deleted 2026-08-16).

collection

collection: BaseCollection

Inherited from

BaseObject.collection

components

components: Component[] = []

Component lane (named reusable 2D/3D definitions) — on the scope for the same UI-reachability reason as textures (Model.components = accessor).

evaluateRoot?

optional evaluateRoot?: () => void

Returns

void

flat?

optional flat?: boolean

Chain-level flat declaration (ModelJSON.flat) — when true, every root scene step is flat-declared (DataNode._flatDeclared reads this).

id

id: string

Inherited from

BaseObject.id

imageUrlOf?

optional imageUrlOf?: (name) => string

Resolve an attached-image reference to its url (wired by Model) — imageData's own scope hook: a url-method parameter KEY resolves to that parameter's literal url; anything else (a raw https:/data: URI) passes through unchanged.

Parameters

name

string

Returns

string

laneHeaders?

optional laneHeaders?: (lane) => Record<string, unknown>[]

One lane's entries reduced to their HEADER fields (key/title/label), in order — wired by Model to a CollectionNode, so reading this registers a membership edge PLUS one edge per entry. Never touches an entry's body, which is what lets a sheet place a table listing every sheet without closing a cycle. Throws on a lane with no collection.

Parameters

lane

string

Returns

Record<string, unknown>[]

layers

layers: Operation[] = []

Layers lane — layer operation nodes (expression args name/color/ lineWidth/lineStyle). Resolved via evaluateLayers() / collectLayers() into Layer records consumed by-name.

listAnimationClips?

optional listAnimationClips?: () => AnimationClip[]

All resolved animation clips for the renderer (lane + baked component clips).

Returns

AnimationClip[]

listAnnotationStyles?

optional listAnnotationStyles?: () => AnnotationStyle[]

Returns

AnnotationStyle[]

listPatterns?

optional listPatterns?: () => Pattern[]

The RESOLVED patterns[] records (wired by Model). A hatch names one and cannot be drawn without it; reading the lane through a hook is what makes editing a pattern re-draw every hatch that names it.

Returns

Pattern[]

listSkeletons?

optional listSkeletons?: () => { data: SkeletonData; key: string; }[]

All resolved skeletons for the renderer (skeleton objects in objects[]). The key rides along: it is the skeleton's only identity.

Returns

{ data: SkeletonData; key: string; }[]

listTextStyles?

optional listTextStyles?: () => TextStyle[]

The RESOLVED textStyles[] / annotationStyles[] records (wired by Model). A drafting-mark producer reads these through the compute context to build its drawn form — see nodesRegistry/wiring.ts's STYLE_AWARE_METHODS. Hooks rather than stored arrays, for the same reason resolveMaterial is one: reading the lane is what makes it a dependency, so editing a style rebuilds the marks that name it.

Returns

TextStyle[]

listTracks?

optional listTracks?: () => Track[]

The full evaluated Track pool a renderer resolves clip/joint/mesh references against — see evaluate/animation.ts's header (consumer-holds-the-reference: an AnimationClip only lists member track KEYS, a BoneEntity's *Track field is a key too; this is where those keys resolve to actual times/values/interpolation).

Returns

Track[]

materials

materials: Operation[] = []

Materials lane — material operation nodes (expression args for every Material field). Resolved via evaluateMaterials() / collectMaterialNodes() into Material records consumed by-name.

name

name: string

nodes?

optional nodes?: NodesLike

owningModel?

optional owningModel?: Model

The Model that owns this scope — wired by Model's constructor (root scope only; an isolated component/texture scope has none). Read by commandRegistry/laneEdit.ts so a panel holding only a scope can still reach the Model-level views lane and settings. Never serialized.

parent?

optional parent?: any

Inherited from

BaseObject.parent

patterns

patterns: Operation[] = []

Patterns lane — pattern operation nodes (expression args name/ lines/lengthSpace). Resolved via evaluatePatterns() / collectPatterns() into Pattern records consumed by-name from a hatch's pattern arg.

refreshTextures?

optional refreshTextures?: () => void

Re-resolve material textureData from the current chains and notify the render sync (wired by Model) — the builder panel's "push texture edits to the 3D scene" hook.

Returns

void

registry?

optional registry?: Registry

resolveMaterial?

optional resolveMaterial?: (name) => unknown

Resolve one materials[] record by name (wired by Model) — Material.get() expression hook. Returns null on miss (fail-soft). Reading registers a materials-lane dependency edge via evaluateMaterials.

Parameters

name

string

Returns

unknown

resolvePlacedComponentBody?

optional resolvePlacedComponentBody?: (key, argsOverride?) => { data: ObjectData; flat: boolean; opening: BrepData[]; }

3D-mode placeComponent hook (wired by Model, root scope) — raw (untransformed) body + opening volumes for one components[] entry, NO flatness gate (see components.ts's FlatLaneExtras.resolvePlacedComponentBody doc — the SAME hook name/shape is also wired onto a component's own isolated "component"-lane scope, for nested 3D placement). flat (the component's own Component.flat declaration) rides along so a flat-declared CHAIN reaching this hook from a 3D lane can splice the body as-is instead of force-flattening it.

Parameters

key

string

argsOverride?

Record<string, string>

Returns

{ data: ObjectData; flat: boolean; opening: BrepData[]; }

data

data: ObjectData

flat

flat: boolean

opening

opening: BrepData[]

resolvePlacedPart?

optional resolvePlacedPart?: (key, argsOverride?, angles?) => ObjectData | undefined

placePart's ROOT-scope hook (wired by Model's constructor) — folds one components[] entry's attributes.pattern content into 3D and returns the grouped placement (see Model._resolvePlacedPart; a part is a components[] entry with attributes.pattern content + consumer-side parameters — tmp/ui-redesign/view-spec.md). argsOverride carries the placement's own parameter overrides (placePart's args arg — same contract as placeComponent's); angles is the per-bend angle override map. Throws a named error on an unknown key / missing pattern content (caught by the calling DataNode's per-step fail-soft).

Parameters

key

string

argsOverride?

Record<string, string>

angles?

Record<string, number>

Returns

ObjectData | undefined

resolvePlacedTable?

optional resolvePlacedTable?: (key) => ObjectData | undefined

Parameters

key

string

Returns

ObjectData | undefined

resolvePlacedView?

optional resolvePlacedView?: (key) => ObjectData | undefined

viewport/tableEntity's ROOT-scope hooks (wired by Model, 2026-07-18 — one-graph law: cross-lane reads are free, cycles rejected by detection, never by a blanket lane-placement ban). Resolve one views[]/tables[] entry into flat, positioned data documents — a narrow-scope tableEntity (explicit entities) never touches the root fold at all; a whole-scene read (a view; a tableSource with no explicit entities) that reaches back into THIS same fold throws a named "Circular dependency" error instead (see Model.ts's sceneFrame / fold-depth guard), caught by the reading node's own per-step fail-soft.

Parameters

key

string

Returns

ObjectData | undefined

resolveSkeleton?

optional resolveSkeleton?: (key) => SkeletonData | undefined

Resolve a skeleton object key to its SkeletonData (wired by Model for faceSkeleton). The object IS the skeleton — its key is the identity.

Parameters

key

string

Returns

SkeletonData | undefined

resolveTable?

optional resolveTable?: (key, operationCount?) => unknown

Resolve one tables[] entry by key (wired by Model) — the Table.get() expression function's hook (see nodes/ExpressionNode.ts). Throws on unknown key. operationCount truncates the body fold (TablesSection verb step preview — same idea as resolveTexture).

Parameters

key

string

operationCount?

number

Returns

unknown

resolveTexture?

optional resolveTexture?: (key, args?, operationCount?) => unknown

Full-chain resolver (wired by Model): evaluate one textures[] entry with optional own-parameter overrides — the builder panel's preview entry. operationCount truncates the chain to its first N steps (per-step thumbnails). Returns an ImageBuffer; throws on unknown key.

Parameters

key

string

args?

Record<string, string>

operationCount?

number

Returns

unknown

sampleTexture?

optional sampleTexture?: (key) => unknown

Texture-lane field resolver (wired by Model): lets a geometry op — displace — consume a math->image chain by key. Cross-stream by design, but one-way: geometry reads pixels, never the reverse.

Parameters

key

string

Returns

unknown

sceneData?

optional sceneData?: () => ObjectData[]

Whole-scene data list for Scene.entities() (wired by Model — flattens sceneFrame() leaves). A root-fold re-entry throws a named "Circular dependency" error (see Model.sceneFrame).

Returns

ObjectData[]

settings?

optional settings?: ModelSettings

Model-level settings (units/activeView/cameraTour) — lives here (like unit) so free functions reach it via node.owner?.settings the same way they already reach unit.

sheets

sheets: Sheet[] = []

Sheet lane (construction drawing sheets) — carried on the scope like the other document lanes, so doc-wide edits that only hold a scope (e.g. a material rename rewriting every by-name reference) reach a sheet's ad hoc operations too.

sourceId

sourceId: string = ""

Inherited from

BaseObject.sourceId

styles

styles: Operation[] = []

Styles lane — style operation nodes (expression args name/ background/shading/exposure/sun/environment). Resolved via evaluateStyles() / collectStyleNodes() into Style records consumed by-name from a views[] viewStyle step.

tables

tables: TableChain[] = []

Table lane (reporting streams) — carried on the scope like the other document lanes, so UI panels + Table.get() reach it through the owner chain (scopeOf(owner)), same as materials/layers/fonts/textures.

templates

templates: Template[] = []

textStyles

textStyles: Operation[] = []

Text styles lane — textStyle operation nodes (font/height/ widthFactor/oblique). Resolved via collectTextStyles() into TextStyle records consumed by-name from a text node and from every annotation style.

textures

textures: Chain[] = []

Texture lane (math->image chains) — carried on the scope like the other document lanes, so UI panels reach it through the owner chain (scopeOf(owner)), same as materials/layers/fonts. Storage key is textures[] on ModelJSON.

unit?

optional unit?: UnitConfig

urlParameterRows?

optional urlParameterRows?: () => { key: string; url: string; }[]

The CURRENT url-method parameter rows ({ key, url } — url = the parameter's literal url, see urlInputLiteral in schema/model.ts), wired by Model and read FRESH on every fonts/images access below — the two views can never go stale, and there is no stored lane state for a UI to write.

Returns

{ key: string; url: string; }[]

Accessors

fonts

Get Signature

get fonts(): AssetFile[]

COMPUTED view over the url-method parameters: one { name: paramKey, url } entry per parameter whose url classifies as a font (assetTypeOf). Read-only — an attached font is edited by editing its parameter.

Returns

AssetFile[]

images

Get Signature

get images(): AssetFile[]

COMPUTED view over the url-method parameters: one { name: paramKey, url } entry per parameter whose url classifies as an image (assetTypeOf) — consumed by sheet placements, the pattern image source, and the imageData generator. Read-only.

Returns

AssetFile[]

model

Get Signature

get model(): any

Returns

any

Inherited from

BaseObject.model

Methods

_dispose()

_dispose(): void

Returns

void

Inherited from

BaseObject._dispose

addListener()

addListener(event, listener): () => void

Parameters

event

string

listener

Listener

Returns

() => void

Inherited from

BaseObject.addListener

bakeValue()

bakeValue(value): ObjectData[]

Bake a chain value (ONE ObjectData, which may be a blockData — clone/array-over-a-group/looseToBlock/makeBlock all produce one) into flat leaf data documents. A node's .model getter resolves to its owning ModelScope, so any node-tree consumer (e.g. a hover preview) reaches this the same way Model.bakeValue does.

Parameters

value

ObjectData | undefined

Returns

ObjectData[]

evaluate()

evaluate(): void

Pull the root fold fresh (see evaluateRoot) — a no-op if this scope was constructed standalone (not via new Model(...), which always wires evaluateRoot).

Returns

void

fromJSON()

static fromJSON(json): ModelScope

Parameters

json

RawModel

Returns

ModelScope

notify()

notify(event, ...args): void

Parameters

event

string

args

...unknown[]

Returns

void

Inherited from

BaseObject.notify

remove()

remove(): void

Returns

void

Inherited from

BaseObject.remove

removeListener()

removeListener(event, listener): void

Parameters

event

string

listener

Listener

Returns

void

Inherited from

BaseObject.removeListener

setName()

setName(name): void

Parameters

name

string

Returns

void

toJSON()

toJSON(): RawModel

Returns

RawModel

Overrides

BaseObject.toJSON


resolveImageUrl()

resolveImageUrl(images, ref): string

Resolve an attached-image reference against the computed url-parameter entries (ModelScope.images): ref may be a url-method parameter KEY (the by-key consumption sheet placements / the pattern image source use) or a literal URI already — a key lookup miss passes ref through unchanged.

Parameters

images

AssetFile[] | undefined

ref

string

Returns

string

Last updated: 📖 13 min readEdit on GitHub