Understand the asset system—how external media and resources like images, stickers, or videos are handled in CE.SDK.
Images, videos, audio, fonts, stickers, and templates—every premade resource you can add to a design is what we call an Asset. The editor gets access to these Assets through Asset Sources. When you apply an Asset, CE.SDK creates or modifies a Block to display that content.
This guide covers the core concepts of the Asset system. For detailed instructions on inserting images, see the Images guide. For related concepts, see Blocks and Resources.
Assets vs Blocks#
Assets are content definitions with metadata (URIs, dimensions, labels) that exist outside the scene. Blocks are the visual elements in the scene tree that display content.
When you apply an asset, CE.SDK creates a block configured according to the asset’s properties. Multiple blocks can reference the same asset, and assets can exist without being used in any block.
The Asset Data Model#
An asset describes content that can be added to designs. Each asset has an id and optional properties:
let stickerAsset = AssetResult( id: "sticker-smile", label: "Smile Sticker", tags: ["emoji", "happy"], meta: [ "uri": "https://cdn.img.ly/assets/v3/ly.img.sticker/images/emoticons/imgly_sticker_emoticons_smile.svg", "thumbUri": "https://cdn.img.ly/assets/v3/ly.img.sticker/images/emoticons/imgly_sticker_emoticons_smile.svg", "blockType": "//ly.img.ubq/graphic", "fillType": "//ly.img.ubq/fill/image", "width": "62", "height": "58", "mimeType": "image/svg+xml", ], context: AssetContext(sourceID: "my-assets"), groups: ["stickers"],)Key properties include:
id— Unique identifier for the assetlabel— Display name (can be localized)tags— Searchable keywordsgroups— Categories for filteringmeta— Content-specific data includinguri,thumbUri,blockType,fillType,width,height, andmimeTypecontext— AnAssetContextthat ties the asset to its source
Asset Sources#
Asset sources provide assets to the editor. Each source conforms to the AssetSource protocol and implements a findAssets(queryData:) method that returns paginated results.
func findAssets(queryData: AssetQueryData) async throws -> AssetQueryResult { AssetQueryResult( assets: [stickerAsset], currentPage: queryData.page, nextPage: -1, total: 1, )}The findAssets(queryData:) callback receives an AssetQueryData with parameters like page, perPage, query, tags, and groups, and returns an AssetQueryResult with assets, total, currentPage, and nextPage.
Sources can also implement optional methods like getGroups(), fetchAsset(id:options:), and apply(asset:) for custom behavior.
Querying Assets#
Search and filter assets from registered sources using findAssets(sourceID:query:):
// Query assets from a registered sourcelet results = try await engine.asset.findAssets( sourceID: "my-assets", query: .init(query: nil, page: 0, perPage: 10),)print("Found assets:", results.total)Results include pagination info. Loop through pages until nextPage is -1 to retrieve all matching assets.
Applying Assets#
Use apply(sourceID:assetResult:) to create a new block from an asset:
// Apply an asset to create a block in the sceneif let asset = results.assets.first { let blockID = try await engine.asset.apply(sourceID: "my-assets", assetResult: asset) print("Created block:", blockID as Any)}The method returns the new block ID, which you can use to position and configure the block.
Local Asset Sources#
Local sources store assets in memory and support dynamic add/remove operations. Use these for user uploads or runtime-generated content:
// Local sources store assets in memory and support dynamic add/removetry engine.asset.addLocalSource(sourceID: "uploads", supportedMimeTypes: ["image/svg+xml", "image/png"])
try engine.asset.addAsset( to: "uploads", asset: AssetDefinition( id: "uploaded-1", meta: [ "uri": "https://cdn.img.ly/assets/v3/ly.img.sticker/images/emoticons/imgly_sticker_emoticons_love.svg", "thumbUri": "https://cdn.img.ly/assets/v3/ly.img.sticker/images/emoticons/imgly_sticker_emoticons_love.svg", "blockType": "//ly.img.ubq/graphic", "fillType": "//ly.img.ubq/fill/image", "mimeType": "image/svg+xml", ], label: ["en": "Heart Sticker"], ),)Source Events#
Subscribe to asset source lifecycle events for reactive UIs:
// Subscribe to asset source lifecycle eventslet task = Task { for await sourceID in engine.asset.onAssetSourceUpdated { print("Source updated:", sourceID) break }}
// Notify that source contents changedtry engine.asset.assetSourceContentsChanged(sourceID: "uploads")
task.cancel()Call assetSourceContentsChanged(sourceID:) after modifying a source to notify subscribers.