Skip to content

Load a Scene

Loading an existing scene allows resuming work on a previous session or adapting an existing template to your needs.

Load Scenes from a Remote URL

Determine a url that points to a scene binary string. Create an instance of Uri using the remote url.

val sceneUri = Uri.parse(
"https://cdn.img.ly/assets/demo/v1/ly.img.template/templates/cesdk_postcard_1.scene",
)

We can then pass the object sceneUri to the suspend fun load(sceneUri: Uri): DesignBlock function. The editor will reset and present the given scene to the user. The function is asynchronous and it does not throw if the scene load succeeded.

val scene = engine.scene.load(sceneUri = sceneUri)

From this point on we can continue to modify our scene. In this example, assuming the scene contains a text element, we add a drop shadow to it. See Modifying Scenes for more details.

val text = engine.block.findByType(DesignBlockType.Text).first()
engine.block.setDropShadowEnabled(text, enabled = true)

Scene loads may be reverted using engine.editor.undo().

To later save your scene, see Saving Scenes.

Full Code

Here’s the full code:

import android.net.Uri
import kotlinx.coroutines.*
import ly.img.engine.*
fun loadSceneFromRemote(
license: String,
userId: String,
) = CoroutineScope(Dispatchers.Main).launch {
val engine = Engine.getInstance(id = "ly.img.engine.example")
engine.start(license = license, userId = userId)
engine.bindOffscreen(width = 100, height = 100)
val sceneUri =
Uri.parse(
"https://cdn.img.ly/assets/demo/v1/ly.img.template/templates/cesdk_postcard_1.scene",
)
val scene = engine.scene.load(sceneUri = sceneUri)
val text = engine.block.findByType(DesignBlockType.Text).first()
engine.block.setDropShadowEnabled(text, enabled = true)
engine.stop()
}

Load Scenes from a String

In this example, we fetch a scene from a remote url and load it as a string. This string could also come from the result of suspend fun saveToString(): String.

val sceneUrl = URL("https://cdn.img.ly/assets/demo/v1/ly.img.template/templates/cesdk_postcard_1.scene")
val sceneBlob = withContext(Dispatchers.IO) {
val outputStream = ByteArrayOutputStream()
sceneUrl.openStream().use { inputStream ->
outputStream.use(inputStream::copyTo)
}
outputStream.toByteArray()
}
val blobString = String(sceneBlob, Charsets.UTF_8)

We can then pass that string to the suspend fun load(scene: String): DesignBlock function. The editor will then reset and present the given scene to the user. The function is asynchronous and it does not throw if the scene load succeeded.

val scene = engine.scene.load(scene = blobString)

From this point on we can continue to modify our scene. In this example, assuming the scene contains a text element, we add a drop shadow to it. See Modifying Scenes for more details.

val text = engine.block.findByType(DesignBlockType.Text).first()
engine.block.setDropShadowEnabled(text, enabled = true)

Scene loads may be reverted using engine.editor.undo().

To later save your scene, see Saving Scenes.

Full Code

Here’s the full code:

import kotlinx.coroutines.*
import ly.img.engine.*
import java.io.ByteArrayOutputStream
import java.net.URL
fun loadSceneFromString(
license: String,
userId: String,
) = CoroutineScope(Dispatchers.Main).launch {
val engine = Engine.getInstance(id = "ly.img.engine.example")
engine.start(license = license, userId = userId)
engine.bindOffscreen(width = 100, height = 100)
val sceneUrl =
URL("https://cdn.img.ly/assets/demo/v1/ly.img.template/templates/cesdk_postcard_1.scene")
val sceneBlob =
withContext(Dispatchers.IO) {
val outputStream = ByteArrayOutputStream()
sceneUrl.openStream().use { inputStream ->
outputStream.use(inputStream::copyTo)
}
outputStream.toByteArray()
}
val blobString = String(sceneBlob, Charsets.UTF_8)
val scene = engine.scene.load(scene = blobString)
val text = engine.block.findByType(DesignBlockType.Text).first()
engine.block.setDropShadowEnabled(text, enabled = true)
engine.stop()
}

Load Scenes From a Blob

In this example, we fetch a scene from a remote url and load it as sceneBlob.

val sceneUrl = URL("https://cdn.img.ly/assets/demo/v1/ly.img.template/templates/cesdk_postcard_1.scene")
val sceneBlob = withContext(Dispatchers.IO) {
val outputStream = ByteArrayOutputStream()
sceneUrl.openStream().use { inputStream ->
outputStream.use(inputStream::copyTo)
}
outputStream.toByteArray()
}

To acquire a scene string from sceneBlob, we need to read its contents into a string.

val blobString = String(sceneBlob, Charsets.UTF_8)

We can then pass that string to the suspend fun load(scene: String): DesignBlock function. The editor will reset and present the given scene to the user. The function is asynchronous and it does not throw if the scene load succeeded.

val scene = engine.scene.load(scene = blobString)

From this point on we can continue to modify our scene. In this example, assuming the scene contains a text element, we add a drop shadow to it. See Modifying Scenes for more details.

val text = engine.block.findByType(DesignBlockType.Text).first()
engine.block.setDropShadowEnabled(text, enabled = true)

Scene loads may be reverted using engine.editor.undo().

To later save your scene, see Saving Scenes.

Full Code

Here’s the full code:

import kotlinx.coroutines.*
import ly.img.engine.*
import java.io.ByteArrayOutputStream
import java.net.URL
fun loadSceneFromBlob(
license: String,
userId: String,
) = CoroutineScope(Dispatchers.Main).launch {
val engine = Engine.getInstance(id = "ly.img.engine.example")
engine.start(license = license, userId = userId)
engine.bindOffscreen(width = 100, height = 100)
val sceneUrl =
URL("https://cdn.img.ly/assets/demo/v1/ly.img.template/templates/cesdk_postcard_1.scene")
val sceneBlob =
withContext(Dispatchers.IO) {
val outputStream = ByteArrayOutputStream()
sceneUrl.openStream().use { inputStream ->
outputStream.use(inputStream::copyTo)
}
outputStream.toByteArray()
}
val blobString = String(sceneBlob, Charsets.UTF_8)
val scene = engine.scene.load(scene = blobString)
val text = engine.block.findByType(DesignBlockType.Text).first()
engine.block.setDropShadowEnabled(text, enabled = true)
engine.stop()
}

Loading Scene Archives

Loading a scene archives requires unzipping the archives contents to a location, that’s accessible to the CreativeEngine. One could for example unzip the archive via unzip archive.zip and then serve its contents using $ npx serve. This spins up a local test server, that serves everything contained in the current directory at http://localhost:3000

The archive can then be loaded by calling engine.scene.load("http://localhost:3000/scene.scene"). See loading scenes for more details. All asset paths in the archive are then resolved relative to the location of the scene.scene file. For an image, that would result in 'http://localhost:3000/images/1234.jpeg'. After loading all URLs are fully resolved with the location of the scene.scene file and the scene behaves like any other scene.

Resolving assets from a different source

The engine will use its URI resolver to resolve all asset paths it encounters. This allows you to redirect requests for the assets contained in archive to a different location. To do so, you can add a custom resolver, that redirects requests for assets to a different location. Assuming you store your archived scenes in a scenes/ directory, this would be an example of how to do so:

engine.editor.setURIResolver {
val uri = java.net.URI(it.path)
if (uri.host == "localhost" && uri.path.startsWith("/scenes") && !uri.path.endsWith(".scene")) {
// Apply custom logic here, e.g. redirect to a different server
}
engine.editor.defaultURIResolver(it)
}