# Pascal Editor Level System Display Modes: Stacked, Exploded, and Solo

> Explore Pascal Editor level system display modes: stacked, exploded, and solo. Understand how these formats control multi-floor building rendering in the 3D viewer.

- Repository: [Pascal/editor](https://github.com/pascalorg/editor)
- Tags: deep-dive
- Published: 2026-03-25

---

**The Pascal Editor level system supports three display modes—stacked, exploded, and solo—that control how multi-floor building levels are positioned and rendered in the 3D viewer.**

The architectural visualization engine in `pascalorg/editor` manages multi-floor displays through the Viewer package's Level System. It reads the current `levelMode` from the global Zustand store and animates every `LevelNode` Object3D each frame. These display modes enable architects to inspect building structures as compact stacked floors, separated exploded views, or isolated single levels.

## Understanding the Three Display Modes

The level system distinguishes between visualization states based on the `levelMode` value stored in `useViewer` ([`packages/viewer/src/store/use-viewer.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/store/use-viewer.ts)).

### Stacked Mode

In **stacked** mode, levels are placed one on top of another using the real computed height of each floor. The system accumulates the actual vertical space occupied by walls and ceilings without adding artificial gaps. Each level's target Y-position equals the cumulative height of all floors beneath it, calculated by `getLevelHeight` in [`packages/viewer/src/systems/level/level-utils.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-utils.ts).

### Exploded Mode

**Exploded** mode maintains the same base stacking logic but inserts a fixed separation gap between floors. According to [`packages/viewer/src/systems/level/level-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-system.tsx), the system adds `EXPLODED_GAP = 5` units multiplied by the level index to create the visual "explosion" effect. This separation makes structural elements between floors visible for detailed inspection while preserving the relative order of levels.

### Solo Mode

**Solo** mode isolates visibility to show only the currently selected level. When `levelMode` is set to `'solo'`, the system evaluates the `selectedLevel` ID from the viewer store. The visibility guard in [`packages/viewer/src/systems/level/level-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-system.tsx) ensures that `obj.visible` remains `true` only for the matching level ID, or for all levels if nothing is selected, effectively hiding all non-selected floors.

## Core Implementation and Animation

The system executes every render frame via `useFrame` with priority `5`, ensuring updates occur after other geometry systems finish processing.

```tsx
// packages/viewer/src/systems/level/level-system.tsx
useFrame((_, delta) => {
  const nodes = useScene.getState().nodes
  const levelMode = useViewer.getState().levelMode
  const selectedLevel = useViewer.getState().selection.levelId
  // ... position and visibility logic
}, 5)

```

For each frame, the system calculates target positions and applies linear interpolation for smooth animation. The cumulative Y offset advances by the true height of each level.

```tsx
const baseY = cumulativeY
const explodedExtra = levelMode === 'exploded' ? index * EXPLODED_GAP : 0
const targetY = baseY + explodedExtra
obj.position.y = lerp(obj.position.y, targetY, delta * 12)

```

The animation uses a lerp factor of `delta * 12` to create responsive yet smooth transitions between display states.

## Height Calculation and Performance

Accurate stacking requires knowing each level's true vertical extent. The `getLevelHeight` function in [`packages/viewer/src/systems/level/level-utils.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-utils.ts) computes this by iterating over a level's children, examining wall mesh positions and ceiling heights, then returning the maximum top value. If no geometry is found, it returns a default height of **2.5 units**.

Results are memoized against the `nodes` object reference, providing O(1) lookups after initial computation. Levels are collected from the scene registry using `sceneRegistry.byType.level` and sorted by their logical floor index (`level?.level`) before processing.

## Changing Display Modes Programmatically

The `levelMode` state lives in the global viewer Zustand store and persists across sessions via `viewer-preferences`.

### Switching to Exploded View

```tsx
import useViewer from '@pascal-app/viewer/src/store/use-viewer';

const showExploded = () => {
  useViewer.getState().setLevelMode('exploded');
};

```

### Focusing on a Single Level

```tsx
import useViewer from '@pascal-app/viewer/src/store/use-viewer';

const focusOnLevel = (levelId: string) => {
  useViewer.getState().setSelection({ levelId });
  useViewer.getState().setLevelMode('solo');
};

```

UI components in the editor package, such as [`packages/editor/src/components/ui/command-palette/index.tsx`](https://github.com/pascalorg/editor/blob/main/packages/editor/src/components/ui/command-palette/index.tsx) and [`packages/editor/src/components/ui/action-menu/view-toggles.tsx`](https://github.com/pascalorg/editor/blob/main/packages/editor/src/components/ui/action-menu/view-toggles.tsx), invoke `setLevelMode` through the same store interface.

## Manual Snap Helper for Static Rendering

When generating high-resolution exports, animated transitions may cause misalignment. The `snapLevelsToTruePositions` helper in [`packages/viewer/src/systems/level/level-utils.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-utils.ts) temporarily forces every level to its exact stacked Y-position, bypassing the current animation mode.

```tsx
import { snapLevelsToTruePositions } from '@pascal-app/viewer/src/systems/level/level-utils';

const restore = snapLevelsToTruePositions();
// Execute render pass here
restore(); // Resume animated positions

```

This function returns a restoration callback that re-enables the animation system after the static render completes.

## Summary

- The **stacked** mode places floors directly atop one another using real computed heights from `getLevelHeight`.
- **Exploded** mode adds a fixed 5-unit gap between floors for structural inspection.
- **Solo** mode hides all non-selected levels via the visibility guard in [`level-system.tsx`](https://github.com/pascalorg/editor/blob/main/level-system.tsx).
- Animation runs each frame via `useFrame` priority 5, lerping positions with a factor of `delta * 12`.
- Height calculations are memoized in [`level-utils.ts`](https://github.com/pascalorg/editor/blob/main/level-utils.ts) for O(1) performance after initial computation.
- Programmatic control is available through `useViewer.getState().setLevelMode()` and `setSelection()`.
- The `snapLevelsToTruePositions` helper enables accurate static renders by temporarily disabling animations.

## Frequently Asked Questions

### How does the Pascal Editor calculate the vertical gap in exploded mode?

The system adds a fixed constant `EXPLODED_GAP` set to 5 units, multiplied by the level's index in the stack. This value is added to the base cumulative height in [`packages/viewer/src/systems/level/level-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-system.tsx) to create the separation effect between floors.

### What happens to level visibility when switching to solo mode?

When `levelMode` is set to `'solo'`, the system evaluates `obj.visible` based on whether the level ID matches the `selectedLevel` from the viewer store. If no level is selected, all levels remain visible; otherwise, only the selected level renders while others are hidden immediately without animation.

### Where is the level display mode state stored in the Pascal Editor?

The state persists in the Zustand store defined in [`packages/viewer/src/store/use-viewer.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/store/use-viewer.ts), which includes the `levelMode` property and `setLevelMode` action. The store persists user preferences via `viewer-preferences` so the selected mode survives page reloads.

### How can I temporarily disable animations for a screenshot export?

Import `snapLevelsToTruePositions` from [`packages/viewer/src/systems/level/level-utils.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-utils.ts) and call it before rendering. This function immediately snaps all levels to their true stacked positions and returns a restore function to resume the animated level system afterward.