002 - Core System
The core system forms the foundation of the cc-toolbox. It solves a central problem: How do I manage the state of a generative artwork so that it's persistable, synchronizable, and controllable via UI?
The answer: A central ParameterObject that serves as the single source of truth. All components read from and write to it. The IOManager coordinates communication, and the TweakpaneManager binds the UI.
Components
| Class | File | Function |
|---|---|---|
Artwork |
Artwork.ts |
Main container, initializes everything |
SketchRunner |
Sketch.ts |
Executes Sketches |
SceneGraph |
SceneGraph.ts |
Manages Drawables/Agents |
ParameterObject |
ParameterObject.ts |
Central State Store |
IOManager |
IOManager.ts |
Event Hub & Channels |
TweakpaneManager |
TweakpaneManager.ts |
UI Module System |
Format |
Format.ts |
Canvas Formats (Screen, Print) |
Viewport |
Viewport.ts |
Responsive Scaling |
Artwork
The central container for each artwork.
Lifecycle:
User Sketch Artwork SceneGraph
│ │ │ │
│ SketchRunner │ │ │
│ .run() │ │ │
│──────────────>│ │ │
│ │ new Artwork() │ │
│ │──────────────>│ │
│ │ │ initCanvas() │
│ │ │ initTweakpane()
│ │ configure() │ │
│ │──────────────>│ │
│ │ │ addAgent() │
│ │ │──────────────>│
│ │ │ │
│ │ ┌──────────────────────────┤
│ │ │ Render Loop │
│ │ │ │
│ │ draw() │ │
│ │<──────────────│ │
│ │ draw() │ │
│ │──────────────────────────────>│
│ │ │ │
│ │ └──────────────────────────┤
│ │ │ │Props:
| Property | Type | Description |
|---|---|---|
canvas |
Canvas |
Canvas Element & Size |
parameter |
ParameterObject |
All Parameters |
tweakpane |
TweakpaneItems |
UI Container |
sceneGraph |
SceneGraph |
Agent Container |
format |
Format |
Active Format |
animation |
AnimationState |
Timing Info |
SceneGraph
Manages all drawable objects (Agents/Drawables).
Features:
- Hierarchical Structure
- Z-Order Management
- Batch Updates
- Visibility Control
API:
| Method | Description |
|---|---|
add(agent) |
Add Agent |
remove(agent) |
Remove Agent |
draw(ctx) |
Draw All Agents |
forEach(fn) |
Iterate Over Agents |
ParameterObject
The ParameterObject is the heart of the architecture. It's a simple JavaScript object that contains the complete state of an artwork – from canvas size to colors to agent-specific settings.
Why so central?
The problem with generative art: You find the perfect setting after hours of tweaking – and lose it on the next reload. The ParameterObject solves this:
- Serializable: Saveable as JSON (Snapshots!)
- Synchronizable: Via Sockets to Studio/other Artworks
- UI-bindable: Tweakpane reads and writes directly to it
- Versionable: Git-friendly, diffable
Structure:
parameter
├── artwork # Artwork Settings
│ ├── canvas
│ └── animation
├── format # Format Settings
├── colorset # Active Colors
├── tweakpane # UI State (prefixed)
│ └── {component}
│ └── {subcomponent}
│ └── {key}: value
└── {agent} # Agent-specific
└── {property}: valueProperties:
- Serializable (JSON)
- Import/Export capable
- Event-capable via IOManager
IOManager
The IOManager is the event hub of the application. It decouples components from each other – no one needs to access other components directly.
The problem without IOManager:
ColorSet changes color → must know all Brushes → tight couplingWith IOManager:
ColorSet → emits "colorset:changed" → IOManager → all Subscribers receive itTwo communication patterns:
Channel-based (Pull)
- For Tweakpane updates
- State-based
onUpdate()Callbacks
Event-based (Pub/Sub)
- For events like
colorset:changed - Payload-based
subscribe()/emit()
- For events like
Example Events:
| Event | Payload | Trigger |
|---|---|---|
colorset:changed |
{ colors, id } |
ColorSet changes |
format:changed |
{ width, height } |
Format changes |
parameter:updated |
{ path, value } |
Parameter changes |
TweakpaneManager
Tweakpane is a fantastic UI library for parameter manipulation. But with complex artworks with many agents, management becomes chaotic: Who writes where? Whose state is that?
The TweakpaneManager solves this through modules with isolated state areas. Each module:
- Has its own namespace in the ParameterObject
- Knows only its own state
- Communicates via IOManager channels
The Brush Pattern is the reference implementation: A Brush module manages parameter.tweakpane.{component}.brush.* and transforms UI values (with prefix brush_) into business logic values (without prefix).
Concept:
TweakpaneManager
├── createModule(options) → TweakpaneModule
│ ├── id: "brush:shape"
│ ├── statePath: ["brush", "shape"]
│ ├── stateDefaults: {...}
│ └── channelId: "ui:brush:shape"
└── modules: Map<id, Module>TweakpaneModule API:
| Method | Description |
|---|---|
addBinding(key, params) |
Add UI Control |
onUpdate(handler) |
Register Update Handler |
getState() |
Read State |
setState(obj) |
Set State |
Format
Predefined canvas formats.
Categories:
| Category | Examples |
|---|---|
| Screen | 1080p, 4K, Instagram Square |
| Print A-Series | A4, A3, A2 (300dpi) |
| Print US | Letter, Legal |
| Custom | Freely definable |
Responsive Behavior:
FitMode: 'contain'- Fit in containerFitMode: 'cover'- Fill containerFitMode: 'none'- Original size
Vector
2D/3D vector operations.
Methods:
| Category | Methods |
|---|---|
| Arithmetic | add, subtract, multiply, divide |
| Length | magnitude, normalize, setMagnitude |
| Angle | angle, rotate, heading |
| Products | dot, cross |
| Interpolation | lerp, slerp |
| Utilities | distance, clone, random |
Coordinate & Size
Helper classes for positions and sizes.
// Coordinate - Row/Col
const coord = new Coordinate(row, col);
// Size - Width/Height
const size = new Size(width, height);
size.area; // → width * height
size.aspect; // → width / heightDebug
Logging and debugging utilities.
Modes:
silent- No outputminimal- Errors onlynormal- Errors + Warningsverbose- Everything
Methods:
| Method | Description |
|---|---|
log(msg) |
Info Log |
warn(msg) |
Warning |
error(msg) |
Error |
time(label) |
Start Timer |
timeEnd(label) |
Stop Timer |