# Pascal Editor Zones for Visibility Control Based on Level Mode: A Technical Deep Dive

> Learn how Pascal Editor zones control visibility based on level mode. Explore the reactive system for dynamic zone and label display in this technical deep dive.

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

---

**Pascal Editor controls zone visibility through a reactive system that reads global state on every frame, showing zones only when the "zones" structure layer is active and hiding zone labels specifically when solo level mode is enabled for non-selected levels.**

Pascal Editor is an open-source building information modeling tool that manages architectural zones through a sophisticated visibility system tied to the current **level mode**. This article examines how the editor determines when to display zone geometry and labels based on real-time state changes in the viewer and editor stores.

## How Zone Visibility Works in Pascal Editor

The core visibility logic resides in **[`packages/editor/src/components/systems/zone/zone-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/editor/src/components/systems/zone/zone-system.tsx)**, a React Three Fiber system that executes during every render frame via `useFrame`. Unlike static visibility toggles, this system continuously evaluates three critical state values to determine whether each zone should appear.

### Global State Dependencies

Zone visibility depends on state from two separate Zustand stores:

- **`structureLayer`** (from `useEditor`): Determines which structural layer is active—must be set to `"zones"` for zone geometry to appear
- **`levelMode`** (from `useViewer`): Controls how levels are presented as **stacked**, **exploded**, **solo**, or **manual**
- **`selection.levelId`** (from `useViewer`): Identifies the currently selected level, relevant only when `levelMode === 'solo'`

### The ZoneSystem Render Loop

During each frame, the system executes a five-step visibility calculation:

1. **Read current state** from both stores:
   ```tsx
   const structureLayer = useEditor.getState().structureLayer
   const levelMode = useViewer.getState().levelMode
   const selectedLevelId = useViewer.getState().selection.levelId
   ```

2. **Determine base layer visibility**—zones only appear when the user has explicitly selected the zones layer:
   ```tsx
   const visible = structureLayer === 'zones'
   ```

3. **Check level ownership and solo mode constraints**. For each zone, the system retrieves its Three.js object and node data, then checks if it belongs to the selected level:
   ```tsx
   const isOnSelectedLevel = zone?.parentId === selectedLevelId
   const hideInSoloMode = levelMode === 'solo' && selectedLevelId && !isOnSelectedLevel
   ```

4. **Update geometry visibility** by setting the Three.js object flag:
   ```tsx
   if (obj.visible !== visible) { obj.visible = visible }
   ```

5. **Control label opacity** independently of geometry. Labels fade out when hiding in solo mode, even if the zone layer remains active:
   ```tsx
   const showLabel = visible && !hideInSoloMode
   const targetOpacity = showLabel ? '1' : '0'
   const labelEl = document.getElementById(`${zoneId}-label`)
   if (labelEl && labelEl.style.opacity !== targetOpacity) {
       labelEl.style.opacity = targetOpacity
   }
   ```

Because this logic runs on every frame, changes to `levelMode` or `structureLayer` propagate instantly to all zones without requiring manual refresh or component remounting.

## Level Modes and Their Impact on Zones

The **level mode** dictates how Pascal Editor presents multiple floor levels in the 3D viewport. While `stacked` and `exploded` modes display all levels simultaneously with different spatial offsets, **`solo` mode** selectively isolates a single level.

When operating in solo mode, the `LevelSystem` (located in [`packages/viewer/src/systems/level/level-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/systems/level/level-system.tsx)) handles the positioning and base visibility of level geometry. The **ZoneSystem** complements this by filtering zone labels: zones whose `parentId` does not match the `selectedLevelId` have their DOM labels set to zero opacity, effectively hiding them from view while preserving the underlying zone data in the scene graph.

## Practical Implementation Examples

The following patterns demonstrate how to programmatically control zone visibility using the Pascal Editor API:

**Switching to solo mode for a specific level:**

```tsx
import { useViewer } from '@pascal-app/viewer'

function isolateLevel(levelId: string) {
  const setLevelMode = useViewer.getState().setLevelMode
  useViewer.getState().selection.setLevelId(levelId)
  setLevelMode('solo')
  // ZoneSystem automatically hides labels for zones not belonging to levelId
}

```

**Activating the zones structure layer:**

```tsx
import useEditor from '@pascal-app/editor/store/use-editor'

function enableZoneVisibility() {
  useEditor.getState().setStructureLayer('zones')
  // All zone objects become visible; labels respect current levelMode
}

```

## Summary

- **Zone visibility** requires `structureLayer === 'zones'` in the editor store, defined in [`packages/editor/src/store/use-editor.tsx`](https://github.com/pascalorg/editor/blob/main/packages/editor/src/store/use-editor.tsx)
- The **ZoneSystem** processes visibility checks every frame in [`packages/editor/src/components/systems/zone/zone-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/editor/src/components/systems/zone/zone-system.tsx)
- **`solo` mode** hides zone labels for zones where `parentId` does not match the selected level ID, while the `LevelSystem` manages the actual geometry visibility
- **Real-time updates** occur through Zustand store subscriptions that trigger the `useFrame` loop in the zone system
- Zone nodes reference their parent level through the `parentId` property defined in [`packages/core/src/schema/nodes/zone.ts`](https://github.com/pascalorg/editor/blob/main/packages/core/src/schema/nodes/zone.ts)

## Frequently Asked Questions

### What determines if a zone is visible in Pascal Editor?

Zone geometry appears only when the `structureLayer` state equals `"zones"` in the editor store. This boolean check happens every frame in the ZoneSystem component, ensuring that switching away from the zones layer immediately hides all zone objects regardless of level mode.

### How does solo mode affect zone labels differently than zone geometry?

While solo mode hides entire levels through the `LevelSystem`, the **ZoneSystem** specifically targets DOM labels. When `levelMode === 'solo'` and a `selectedLevelId` exists, zones with a `parentId` mismatching the selected level have their label opacity set to `"0"`, making them invisible even though the zone geometry is already hidden by the layer-level toggle.

### Where is the relationship between zones and levels defined in the source code?

The connection exists in [`packages/core/src/schema/nodes/zone.ts`](https://github.com/pascalorg/editor/blob/main/packages/core/src/schema/nodes/zone.ts), where the zone node schema includes a `parentId` field referencing the level. The ZoneSystem uses this field in [`packages/editor/src/components/systems/zone/zone-system.tsx`](https://github.com/pascalorg/editor/blob/main/packages/editor/src/components/systems/zone/zone-system.tsx) at line 23 to determine if a zone belongs to the currently selected level when filtering for solo mode.

### Can zones be visible when the editor is in manual level mode?

Yes. In **manual** mode, the ZoneSystem does not apply the solo-mode filter (`hideInSoloMode` evaluates to false), so zones remain visible provided the `structureLayer` is set to zones. Manual mode leaves visibility decisions to the user without automatic level-based filtering.