Some design blocks in CE.SDK allow you to modify or replace their fill. The fill is an object that defines the contents within the shape of a block. CreativeEditor SDK supports many different types of fills, such as images, solid colors, gradients and videos.
Similarly to blocks, each fill has a numeric id which can be used to query and modify its properties.
We currently support the following fill types:
FillType.color
FillType.linearGradient
FillType.radialGradient
FillType.conicalGradient
FillType.image
FillType.video
FillType.pixelStream
Accessing Fills
Not all types of design blocks support fills, so you should always first call the func supportsFill(_ id: DesignBlockID) throws -> Bool
API before accessing any of the following APIs.
try engine.block.supportsFill(scene) // Returns falsetry engine.block.supportsFill(block) // Returns true
In order to receive the fill id of a design block, call the func getFill(_ id: DesignBlockID) throws -> DesignBlockID
API. You can now pass this id into other APIs in order to query more information about the fill, e.g. its type via the func getType(_ id: DesignBlockID) throws -> String
API.
let colorFill = try engine.block.getFill(block)let defaultRectFillType = try engine.block.getType(colorFill)
Fill Properties
Just like design blocks, fills with different types have different properties that you can query and modify via the API. Use func findAllProperties(_ id: DesignBlockID) throws -> [String]
in order to get a list of all properties of a given fill.
For the solid color fill in this example, the call would return ["fill/color/value", "type"]
.
Please refer to the design blocks for a complete list of all available properties for each type of fill.
let allFillProperties = try engine.block.findAllProperties(colorFill)
Once we know the property keys of a fill, we can use the same APIs as for design blocks in order to modify those properties. For example, we can use func setColor(_ id: DesignBlockID, property: String, color: Color) throws
in order to change the color of the fill to red.
Once we do this, our graphic block with rect shape will be filled with solid red.
try engine.block.setColor(colorFill, property: "fill/color/value", color: .rgba(r: 1.0, g: 0.0, b: 0.0, a: 1.0))
Disabling Fills
You can disable and enable a fill using the func setFillEnabled(_ id: DesignBlockID, enabled: Bool) throws
API, for example in cases where the design block should only have a stroke but no fill. Notice that you have to pass the id of the design block and not of the fill to the API.
try engine.block.setFillEnabled(block, enabled: false)try engine.block.setFillEnabled(block, enabled: !engine.block.isFillEnabled(block))
Changing Fill Types
All design blocks that support fills allow you to also exchange their current fill for any other type of fill. In order to do this, you need to first create a new fill object using func createFill(_ type: FillType) throws -> DesignBlockID
.
let imageFill = try engine.block.createFill(.image)try engine.block.setString( imageFill, property: "fill/image/imageFileURI", value: "https://img.ly/static/ubq_samples/sample_1.jpg")
In order to assign a fill to a design block, simply call func setFill(_ id: DesignBlockID, fill: DesignBlockID) throws
. Make sure to delete the previous fill of the design block first if you don’t need it any more, otherwise we will have leaked it into the scene and won’t be able to access it any more, because we don’t know its id.
Notice that we don’t use the appendChild
API here, which only works with design blocks and not fills.
When a fill is attached to one design block, it will be automatically destroyed when the block itself gets destroyed.
try engine.block.destroy(colorFill) try engine.block.setFill(block, fill: imageFill)
/* The following line would also destroy imageFill */ // try engine.block.destroy(circle)
Duplicating Fills
If we duplicate a design block with a fill that is only attached to this block, the fill will automatically be duplicated as well. In order to modify the properties of the duplicate fill, we have to query its id from the duplicate block.
let duplicateBlock = try engine.block.duplicate(block) try engine.block.setPositionX(duplicateBlock, value: 450) let autoDuplicateFill = try engine.block.getFill(duplicateBlock) try engine.block.setString( autoDuplicateFill, property: "fill/image/imageFileURI", value: "https://img.ly/static/ubq_samples/sample_2.jpg" )
// let manualDuplicateFill = try engine.block.duplicate(autoDuplicateFill) // /* We could now assign this fill to another block. */ // try engine.block.destroy(manualDuplicateFill)
Sharing Fills
It is also possible to share a single fill instance between multiple design blocks. In that case, changing the properties of the fill will apply to all of the blocks that it’s attached to at once.
Destroying a block with a shared fill will not destroy the fill until there are no other design blocks left that still use that fill.
let sharedFillBlock = try engine.block.create(.graphic) try engine.block.setShape(sharedFillBlock, shape: engine.block.createShape(.rect)) try engine.block.setPositionX(sharedFillBlock, value: 350) try engine.block.setPositionY(sharedFillBlock, value: 400) try engine.block.setWidth(sharedFillBlock, value: 100) try engine.block.setHeight(sharedFillBlock, value: 100) try engine.block.appendChild(to: page, child: sharedFillBlock)
try engine.block.setFill(sharedFillBlock, fill: engine.block.getFill(block))
Full Code
Here is the full code for working with fills:
import Foundationimport IMGLYEngine
@MainActorfunc usingFills(engine: Engine) async throws { let scene = try engine.scene.create()
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)
try await engine.scene.zoom(to: page, paddingLeft: 40, paddingTop: 40, paddingRight: 40, paddingBottom: 40)
let block = try engine.block.create(.graphic) try engine.block.setShape(block, shape: engine.block.createShape(.rect)) try engine.block.setWidth(block, value: 100) try engine.block.setHeight(block, value: 100) try engine.block.setFill(block, fill: engine.block.createFill(.color)) try engine.block.appendChild(to: page, child: block)
try engine.block.supportsFill(scene) // Returns false try engine.block.supportsFill(block) // Returns true
let colorFill = try engine.block.getFill(block) let defaultRectFillType = try engine.block.getType(colorFill) let allFillProperties = try engine.block.findAllProperties(colorFill) try engine.block.setColor(colorFill, property: "fill/color/value", color: .rgba(r: 1.0, g: 0.0, b: 0.0, a: 1.0))
try engine.block.setFillEnabled(block, enabled: false) try engine.block.setFillEnabled(block, enabled: !engine.block.isFillEnabled(block))
let imageFill = try engine.block.createFill(.image) try engine.block.setString( imageFill, property: "fill/image/imageFileURI", value: "https://img.ly/static/ubq_samples/sample_1.jpg" )
try engine.block.destroy(colorFill) try engine.block.setFill(block, fill: imageFill)
/* The following line would also destroy imageFill */ // try engine.block.destroy(circle)
let duplicateBlock = try engine.block.duplicate(block) try engine.block.setPositionX(duplicateBlock, value: 450) let autoDuplicateFill = try engine.block.getFill(duplicateBlock) try engine.block.setString( autoDuplicateFill, property: "fill/image/imageFileURI", value: "https://img.ly/static/ubq_samples/sample_2.jpg" )
// let manualDuplicateFill = try engine.block.duplicate(autoDuplicateFill) // /* We could now assign this fill to another block. */ // try engine.block.destroy(manualDuplicateFill)
let sharedFillBlock = try engine.block.create(.graphic) try engine.block.setShape(sharedFillBlock, shape: engine.block.createShape(.rect)) try engine.block.setPositionX(sharedFillBlock, value: 350) try engine.block.setPositionY(sharedFillBlock, value: 400) try engine.block.setWidth(sharedFillBlock, value: 100) try engine.block.setHeight(sharedFillBlock, value: 100) try engine.block.appendChild(to: page, child: sharedFillBlock)
try engine.block.setFill(sharedFillBlock, fill: engine.block.getFill(block))}