Migrating from Legacy Scripting
This guide helps you migrate existing Mattercraft projects from the legacy JSDoc-based scripting system to the modern decorator-based approach.
Before You Start
Section titled “Before You Start”- Update your dependencies - Ensure all
@zcomponent/*packages are updated to the latest version - Back up your project - Make a copy before making changes
- Migrate incrementally - You can have legacy and modern scripts in the same project during migration
Quick Reference
Section titled “Quick Reference”Class Decorators
Section titled “Class Decorators”| Legacy (JSDoc) | Modern (Decorators) |
|---|---|
/** @zbehavior */ |
@zBehavior({ icon: 'favorite' }) |
/** @zcomponent */ |
@zComponent({ icon: 'favorite' }) |
/** @zcontext */ |
@zContext() |
/** @zicon favorite */ |
@zBehavior({ icon: 'favorite' }) |
Property Decorators
Section titled “Property Decorators”| Legacy (JSDoc) | Modern (Decorators) |
|---|---|
/** @zui */ |
Not needed - properties are visible by default |
/** @zui */ /** @zgroup Settings */ |
@zUI({ group: 'Settings' }) |
/** @zui */ /** @ztype proportion */ |
@zUI({ type: 'proportion' }) |
/** @zdefault 0 */ |
Set value directly: property = 0 |
new Observable(value) |
Plain property with @zObserve() |
Public properties are now visible in the editor by default. Use
@zUI()only when you need to customize appearance (grouping, type hints). Use@zIgnore()to hide a property.
Lifecycle and Events
Section titled “Lifecycle and Events”| Legacy Pattern | Modern Decorator |
|---|---|
this.register(useOnBeforeRender(ctx), fn) |
@zOnBeforeRender() on method |
this.register(useOnAfterRender(ctx), fn) |
@zOnAfterRender() on method |
registerLoadable(ctx, fn()) |
@zLoad() on async method |
this.register(this.instance.onClick, fn) |
@zRegister('onClick') on method |
registerBehaviorRunAtDesignTime(Class) |
@zBehavior({ runAtDesignTime: true }) |
Migrating a Behavior
Section titled “Migrating a Behavior”Legacy Behavior
Section titled “Legacy Behavior”import { Behavior, ContextManager } from "@zcomponent/core";import { Box } from "@zcomponent/three/lib/components/meshes/Box";import { default as Scene } from "./Scene.zcomp";
interface ConstructionProps {}
/** * @zbehavior * @zicon rotate_right */export class RotateBehavior extends Behavior<Box> { protected zcomponent = this.getZComponentInstance(Scene);
constructor( contextManager: ContextManager, instance: Box, protected constructorProps: ConstructionProps ) { super(contextManager, instance);
this.register(useOnBeforeRender(contextManager), dt => { this.instance.element.rotation.y += 0.01 * dt; });
this.register(this.instance.onClick, () => { console.log('Clicked!'); }); }}Modern Behavior
Section titled “Modern Behavior”import { Behavior, zBehavior, zOnBeforeRender, zRegister } from '@zcomponent/core';import { Box } from '@zcomponent/three/lib/components/meshes/Box';
@zBehavior({ icon: 'rotate_right' })export class RotateBehavior extends Behavior<Box> {
@zOnBeforeRender() private _rotate(deltaTime: number) { this.instance.element.rotation.y += 0.01 * deltaTime; }
@zRegister('onClick') private _handleClick() { console.log('Clicked!'); }}Key Changes
Section titled “Key Changes”- Class decorator - Replace
/** @zbehavior */with@zBehavior({ icon: '...' }) - Frame loop - Replace
this.register(useOnBeforeRender(...))with@zOnBeforeRender()method decorator - Events - Replace
this.register(event, fn)with@zRegister('eventName')method decorator - Remove constructor boilerplate - Most logic moves from constructor to decorated methods
Migrating a Component
Section titled “Migrating a Component”Legacy Component
Section titled “Legacy Component”import { ContextManager, registerLoadable } from "@zcomponent/core";import { Group } from "@zcomponent/three/lib/components/Group";import * as THREE from "three";
interface ConstructorProps {}
/** * @zcomponent * @zicon favorite */export class MySphere extends Group {
constructor(contextManager: ContextManager, constructorProps: ConstructorProps) { super(contextManager, constructorProps); registerLoadable(contextManager, this._load()); }
private async _load() { const mesh = new THREE.Mesh( new THREE.SphereGeometry(), new THREE.MeshBasicMaterial() ); this.element.add(mesh); }}Modern Component
Section titled “Modern Component”import { ContextManager, zComponent, zLoad } from '@zcomponent/core';import { Group } from '@zcomponent/three/lib/components/Group';import * as THREE from 'three';
@zComponent({ icon: 'favorite' })export class MySphere extends Group {
@zLoad() private async _load() { const mesh = new THREE.Mesh( new THREE.SphereGeometry(), new THREE.MeshBasicMaterial() ); this.element.add(mesh); }}Key Changes
Section titled “Key Changes”- Class decorator - Replace
/** @zcomponent */with@zComponent({ icon: '...' }) - Async loading - Replace
registerLoadable(ctx, fn())with@zLoad()on the method - Cleaner constructor - Remove boilerplate from constructor
Migrating Properties
Section titled “Migrating Properties”Legacy Properties
Section titled “Legacy Properties”/** * @zui * @zdefault 0 * @zgroup Appearance */public metalness = new Observable(0);
constructor(...) { this.register(this.metalness, value => { this.material.metalness = value; });}Modern Properties
Section titled “Modern Properties”// Simple property - no decorators needed for basic visibilitypublic metalness = 0;
// With reactive updates@zObserve((value, instance) => { instance.material.metalness = value;})public metalness = 0;
// With UI customization (grouping, type hints)@zUI({ group: 'Appearance', type: 'proportion' })@zObserve((value, instance) => { instance.material.metalness = value;})public metalness = 0;Tips for Migration
Section titled “Tips for Migration”- Start with behaviors - They’re usually simpler and give you practice with the new patterns
- Test incrementally - Migrate one script at a time and test after each change
- Use autocomplete - The modern system has excellent TypeScript support
- Check the console - Decorator errors will show helpful messages
Need Help?
Section titled “Need Help?”- Custom Behaviors - Full documentation for behaviors
- Custom Components - Full documentation for components
- Properties - Full documentation for properties
- API Reference - Complete API documentation