Skip to content

Refactor node layout to use relative offsets and add play-mode guards - #60

Draft
chelproc wants to merge 7 commits into
mainfrom
20260606
Draft

Refactor node layout to use relative offsets and add play-mode guards#60
chelproc wants to merge 7 commits into
mainfrom
20260606

Conversation

@chelproc

@chelproc chelproc commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Rework the node renderer around a layout → geometry two-step, generalize bit width handling around per-pin policies, and build on both to add a Const intrinsic component, display config editing, and play-mode guards.

Renderer: layout → geometry split

  • Layout / LayoutSource types split out from Geometry: a layout is a size plus relative pin offsets (nodePinOffsetById), and ccComponentEditorRendererLayoutToGeometry turns it into absolute positions
  • Node SVG wrapper switched from <g> to <svg> so child renderers draw in local coordinates and can use percentage dimensions (Default uses width="100%")
  • Display layout now scales with config.resolution and shares its constants with the renderer; pixel fill indexes inputValue in row-major order (fixes the previously reversed pixel order)
  • Display nodes get a working config settings popover (ConfigSettingButton) for editing the resolution, and now compose the Default renderer for their frame

New Const intrinsic component

  • New CONST type with config: { data: SimulationValue }; the output bit width is calculated from config.data.length and evaluate writes the configured data to the output pin
  • Dedicated renderer and layout calculator (the renderer currently shows placeholder random data instead of config.data)
  • Intrinsic evaluate functions now receive the node config as a fourth argument

Bit width policy refactor

  • The fixed policy is renamed to calculated, and isBitWidthConfigurable / isSplittable are folded into the configurable policy
  • CCComponentPinBitWidthStatus fixMode manual is replaced by nodeDependent: such widths come from a node's config and/or manually specified pin widths, so they can only be resolved per node
  • getNodePinBitWidthStatus is rewritten to be policy-driven — the hard-coded special cases for aggregate / decompose / broadcast pins are gone; manual bit widths are collected per pin key and fed to calculateBitWidth
  • Bit width results are cached in CCNodePinStore, invalidated on node pin / connection changes and on node config updates (new didUpdateConfig event on the node store)
  • New hasCompatibleBitWidths helper used by isConnectable; connections that a config change makes inconsistent (e.g. changing a display resolution) are dropped, and existing connections are re-validated when a new one is registered
  • New unit tests in nodePin.test.ts covering bit width resolution (input / display / aggregate / decompose / broadcast) and connection consistency across config changes

Play mode & simulation

  • isEachInputPinConnected utility and useCanSimulate hook disable the ViewModeSwitcher play button while any input pin is unconnected
  • executeSimulation decoupled from raw node / connection store events in the core slice
  • Input values are keyed by { componentPinId, timeStep } objects with explicit serialization instead of JSON.stringify of a tuple; initial values derive their bit width from the pin's implementation node pin

Separate node layout (relative pin offsets) from geometry (absolute
positions), replacing the single geometry calculator with a
layout → geometry two-step. Switch node SVG wrapper from <g> to <svg>
so child elements can use percentage dimensions. Update Display node
to compute its size from config resolution and add a config settings
button stub. Disable the ViewModeSwitcher play button when any input
pin is unconnected. Remove redundant node/connection event listeners
from the simulation trigger.

Key changes covered:
- Layout / LayoutSource types split out from Geometry, with nodePinOffsetById replacing absolute positions
- <g> → <svg> in Node/index.tsx so Default can use width="100%"
- Display/geometry.ts now scales with config.resolution and exports layout constants
- New ConfigSettingButton component for Display nodes
- isEachInputPinConnected utility in component.ts gating the play button
- executeSimulation decoupled from raw store events in the core slice
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 6, 2026

Copy link
Copy Markdown

Deploying create-cpu-c8345196-9409-4cce-afc4-389f413ad8ee with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6f7b936
Status: ✅  Deploy successful!
Preview URL: https://86813bcf.create-cpu-c8345196-9409-4cce-afc4-389f413ad8ee.pages.dev
Branch Preview URL: https://20260606.create-cpu-c8345196-9409-4cce-afc4-389f413ad8ee.pages.dev

View logs

chelproc and others added 6 commits June 14, 2026 18:21
  - Make the display ConfigSettingButton functional: open a Popover form
    to edit resolution (x/y) and persist via store.nodes.update
  - Compute display node size from config inside the layout calculator
  - Cache getNodePinBitWidthStatus results, invalidating on node/pin/
    connection register/unregister/update events
  - Switch input value bit-width init to getNodePinBitWidthStatus and
    deprecate getComponentPinBitWidthStatus
  - Convert InputValueKey from a tuple to a { componentPinId, timeStep }
    object with a serializeInputValueKey helper
  - Add a reactive useCanSimulate selector and use it to drive the
    ViewModeSwitcher disabled state
- Add CONST intrinsic component with fixed-bit-width output driven by
  configured data, plus a dedicated renderer and layout calculator
- Pass node config to intrinsic evaluate functions
- Fix Display renderer pixel indexing to use row-major order directly
- Remove FlipFlop debug log; log pin bit widths on fixed-width mismatch
The bit width of a pin was resolved by getComponentPinBitWidthStatus,
which only knows the component pin definition. A `fixed` policy was
therefore evaluated against `definition.initialConfig`, so changing the
resolution of a display never changed the bit width of its Pixels pin.
For the same reason aggregate and decompose could not be evaluated
there at all and were special cased into a `manual` fix mode, with
their widths recomputed by hand in CCNodePinStore.

Split the two concerns: getComponentPinBitWidthStatus now only reports
how a width is determined (`automatic` or `nodeDependent`), and
getNodePinBitWidthStatus resolves it from the config of the node and
the manual bit widths of its pins. The `fixed` policy is renamed to
`calculated` to match, and the duplicated per-node calculations for
aggregate and decompose are gone.

Bit widths are cached, so CCNodeStore now emits `didUpdateConfig`, kept
separate from `didUpdate` so that frequent position updates do not drop
the cache. Because a width can now change after a connection was made,
connections whose ends no longer agree are dropped when the config
changes.

Also derive whether a pin is configurable and splittable from its bit
width policy instead of duplicating it on the pin attributes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Const intrinsic was merged in with the `fixed` bit width policy,
which is now named `calculated`. Its output width comes from the config
of the node, so it is resolved per node like the display resolution.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants