undefined} />
+
+
+
{resolvedDeck?.deck.title ?? 'CA Deck'}
{activeScene ? `${sceneIndex + 1}/${resolvedDeck?.scenes.length ?? 0}` : status}
@@ -3310,8 +3603,10 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
const [ruleId, setRuleId] = React.useState('B3/S23')
const [boundaryCondition, setBoundaryCondition] = React.useState('wrap')
const [cells, setCells] = React.useState(() => placeGliderCells())
+ const [runtimeSettings, setRuntimeSettings] = React.useState(null)
const [generation, setGeneration] = React.useState(0)
const [running, setRunning] = React.useState(false)
+ const [speedLevel, setSpeedLevel] = React.useState(DEFAULT_SPEED_LEVEL)
const [status, setStatus] = React.useState('Loading deck...')
const hydratedRef = React.useRef(false)
const deckTitleHydratedRef = React.useRef(false)
@@ -3325,12 +3620,25 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
const selectedNode = nodes.find((node) => node.id === selectedNodeId) ?? null
const assignedNodeId = activeScene?.scene.preset_node_id
const pickerSelectedNode = pickerNodes.find((node) => node.id === pickerSelectedNodeId) ?? null
+ const selectedNodeBaseSettings = selectedNode
+ ? (mergeParamObjects(resolveParentParams(nodes, selectedNode), selectedNode.params) as SceneParams)
+ : null
+ const selectedNodeBaseClass = getCaClassFromParams(selectedNodeBaseSettings ?? undefined)
const resolvedNodeSettings = selectedNode
? (mergeParamObjects(
- mergeParamObjects(resolveParentParams(nodes, selectedNode), selectedNode.params),
- createShotParams(ruleId, neighborhoodId, rendererId, cells, undefined, boundaryCondition)
+ selectedNodeBaseSettings ?? {},
+ createShotParams(
+ ruleId,
+ neighborhoodId,
+ rendererId,
+ cells,
+ undefined,
+ boundaryCondition,
+ shouldProjectCellsIntoSettings(selectedNodeBaseClass)
+ )
) as SceneParams)
: createShotParams(ruleId, neighborhoodId, rendererId, cells, undefined, boundaryCondition)
+ const previewSettings = runtimeSettings ?? resolvedNodeSettings
const refreshDeck = React.useCallback(async () => {
const loadedDeck = await api(`/api/ca/decks/${deckId}`)
@@ -3419,11 +3727,15 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
React.useEffect(() => {
if (!running) return
const timer = window.setInterval(() => {
- setCells((current) => stepCaCells(current, resolvedNodeSettings))
+ setCells((current) => {
+ const stepped = stepCaSimulation(current, previewSettings)
+ setRuntimeSettings(stepped.settings)
+ return stepped.cells
+ })
setGeneration((current) => current + 1)
- }, 220)
+ }, playbackIntervalMs(speedLevel))
return () => window.clearInterval(timer)
- }, [ruleId, running])
+ }, [previewSettings, running, speedLevel])
React.useEffect(() => {
if (!deck || deckTitleHydratedRef.current || deckTitle === deck.title) return
@@ -3504,6 +3816,7 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
])
setNodes(treeNodes)
setSelectedNodeId(nodeId)
+ setRuntimeSettings(null)
setSceneName(node.name || fallbackName || 'Untitled node')
setRendererId(resolved.params.renderer?.id ?? '2d-canvas')
setNeighborhoodId(resolved.params.simulation?.neighborhoodId ?? 'moore')
@@ -3527,10 +3840,12 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
setCaption(typeof scene.scene.params.caption === 'string' ? scene.scene.params.caption : '')
setAutoplayOnSlideChange(shouldAutoplay)
if (scene.scene.preset_tree_id && scene.scene.preset_node_id) {
+ setRuntimeSettings(null)
void loadNodeById(scene.scene.preset_tree_id, scene.scene.preset_node_id, scene.scene.title, { runAfterLoad: shouldAutoplay })
return
}
setSelectedNodeId('')
+ setRuntimeSettings(null)
setSceneName('No CA preset')
setCells(emptyCells())
setGeneration(0)
@@ -3708,7 +4023,11 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
function previewStep() {
setRunning(false)
- setCells((current) => stepCaCells(current, resolvedNodeSettings))
+ setCells((current) => {
+ const stepped = stepCaSimulation(current, previewSettings)
+ setRuntimeSettings(stepped.settings)
+ return stepped.cells
+ })
setGeneration((current) => current + 1)
}
@@ -3785,7 +4104,7 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
@@ -3841,7 +4160,7 @@ function DeckEditor({ deckId, initialSceneId }: { deckId: string; initialSceneId
{activeScene ? slideTitle : sceneName}