Search Docs
Loading...
Skip to content

Scenes

Scenes are the root container for all designs in CE.SDK. They hold pages, blocks, and the camera that controls what you see in the canvas—and the engine manages only one active scene at a time.

10 mins
estimated time
GitHub

Every design you create starts with a scene. Scenes contain pages, and pages contain the visible design elements—text, images, shapes, and other blocks. Understanding how scenes work is essential for building, saving, and restoring user designs.

This guide covers how to create scenes from scratch, manage pages within scenes, configure scene properties, save and load designs, and control the camera’s zoom and position.

Scene Hierarchy#

Scenes form the root of CE.SDK’s design structure. The hierarchy works as follows:

  • Scene — The root container holding all design content
  • Pages — Direct children of scenes, arranged according to the scene’s layout
  • Blocks — Design elements (text, images, shapes) that belong to pages

Only blocks attached to pages within the active scene are rendered in the canvas. Use engine.scene.get() to retrieve the current scene and engine.scene.getPages() to access its pages.

Creating Scenes#

Creating an Empty Scene#

Use engine.scene.create(sceneLayout:) to create a new design scene with a configurable page layout. The sceneLayout parameter controls how pages are arranged in the canvas.

let scene = try engine.scene.create(sceneLayout: .verticalStack)

Available layouts:

LayoutDescription
.verticalStackPages arranged vertically
.horizontalStackPages arranged horizontally
.depthStackPages layered on top of each other
.freeManual positioning (default)

Creating for Video Editing#

For video projects, use engine.scene.createVideo() which configures the scene for timeline-based editing. Unlike create(sceneLayout:), this method takes no parameters — page dimensions are set separately after creation.

Creating from Media Files#

Create scenes directly from images or videos using engine.scene.create(fromImage:) and engine.scene.create(fromVideo:). The scene dimensions match the source media.

Adding Pages#

After creating a scene, add pages using engine.block.create(.page). Configure the page dimensions and append it to the scene.

let page = try engine.block.create(.page)
try engine.block.setWidth(page, value: 800)
try engine.block.setHeight(page, value: 600)
try engine.block.appendChild(to: scene, child: page)

Adding Blocks#

With pages in place, add design elements like shapes, text, or images. Create a graphic block, configure its shape and fill, then append it to a page.

let block = try engine.block.create(.graphic)
let shape = try engine.block.createShape(.rect)
try engine.block.setShape(block, shape: shape)
let fill = try engine.block.createFill(.color)
try engine.block.setFill(block, fill: fill)
try engine.block.setWidth(block, value: 200)
try engine.block.setHeight(block, value: 200)
try engine.block.appendChild(to: page, child: block)

Scene Properties#

Design Units#

Query or configure how measurements are interpreted using engine.scene.getDesignUnit() and engine.scene.setDesignUnit(). This is useful for print workflows where precise physical dimensions matter.

let designUnit = try engine.scene.getDesignUnit()
print("Design unit: \(designUnit)")
try engine.scene.setDesignUnit(.mm)
let layout = try engine.scene.getLayout()
print("Layout: \(layout)")

Supported units are .px, .mm, and .in.

Scene Layout#

Control how pages are arranged using engine.scene.getLayout() and engine.scene.setLayout(). The layout affects how users navigate between pages in multi-page designs.

Access pages within your scene using these methods:

let pages = try engine.scene.getPages()
print("Number of pages: \(pages.count)")
let currentPage = try engine.scene.getCurrentPage()
print("Current page: \(String(describing: currentPage))")

getCurrentPage() returns the page nearest to the viewport center—useful for determining which page the user is currently viewing. For more advanced block queries, use engine.scene.findNearestToViewPortCenter(byType:) and engine.scene.findNearestToViewPortCenter(byKind:).

Camera and Zoom#

Zoom to Block#

Use engine.scene.zoom(to:) to frame a specific block in the viewport with padding. Pass the scene block to show all pages.

try await engine.scene.zoom(to: page, paddingLeft: 20, paddingTop: 20, paddingRight: 20, paddingBottom: 20)
let zoomLevel = try engine.scene.getZoom()
print("Zoom level: \(zoomLevel)")
try engine.scene.setZoom(1.0)

Zoom Level#

Get and set the zoom level directly with engine.scene.getZoom() and engine.scene.setZoom(). A zoom level of 1.0 means one design unit equals one screen pixel.

Auto-Fit Zoom#

For continuous auto-framing, use engine.scene.enableZoomAutoFit() to automatically keep a block centered as the viewport resizes. Disable it with engine.scene.disableZoomAutoFit() and check the current state with engine.scene.isZoomAutoFitEnabled().

Saving Scenes#

Saving to String#

Use engine.scene.saveToString() to serialize the current scene. This captures the complete scene structure—pages, blocks, and their properties—as a string you can store.

let savedScene = try await engine.scene.saveToString()
print("Scene saved, length: \(savedScene.count)")

The serialized string references external assets by URL rather than embedding them. For complete portability including assets, use engine.scene.saveToArchive().

Loading Scenes#

Loading from String#

Use engine.scene.load(from:) to restore a scene from a saved string:

let loadedScene = try await engine.scene.load(from: savedScene)
print("Scene loaded: \(loadedScene)")

Loading a new scene replaces any existing scene. The engine only holds one active scene at a time.

Loading from URL#

Use engine.scene.load(from:) with a URL to load a scene directly from a local/remote location. For scene bundles that include all referenced assets, use engine.scene.loadArchive(from:).

Applying Templates#

Apply template content to the current scene using engine.scene.applyTemplate(from:), which accepts either a URL or a String. Template content is automatically scaled to fit the current page dimensions.

Event Subscriptions#

Subscribe to scene-related events using Swift’s AsyncStream to react to changes in real time.

let zoomTask = Task {
for await _ in engine.scene.onZoomLevelChanged {
let zoom = try engine.scene.getZoom()
print("Zoom changed: \(zoom)")
}
}
let activeTask = Task {
for await _ in engine.scene.onActiveChanged {
print("Active scene changed")
}
}
zoomTask.cancel()
activeTask.cancel()
EventDescription
onZoomLevelChangedFires when the zoom level changes
onActiveChangedFires when the active scene changes

Next Steps#

  • Blocks — Create and manipulate design elements within pages