Macro aframe::component_def

source ·
macro_rules! component_def {
    (
        $(dependencies: $($deps:expr),*;)? 
        $(schema: $schema:expr,)?
        $(multiple: $mult:expr,)? 
        $(init: $init:expr,)?
        $(update: $update:expr,)?
        $(tick: $tick:expr,)?
        $(tock: $tock:expr,)?
        $(remove: $remove:expr,)?
        $(pause: $pause:expr,)?
        $(play: $play:expr,)?
        $(update_schema: $update_schema:expr,)?
    ) => { ... };
}
Expand description

Top-level macro to define components. Usage resembles struct creation syntax. The js! macro is available for writing inline javascript, and returns a js_sys::Function object. This macro calls into on expressions passed into the fields expecting function, allowing the js! macro to be used as a catch-all. Takes the optional fields described in the table below.

fieldsyntax explanationdescription
dependenciesstrings separated by commasnames of components that must be initialized prior to this one
schemaA hashmap containing string keys and ComponentProperty values. Recommend the maplit crateDescribes component properties
multipleboolean valueTrue to allow multiple components on a single entity
initJsValue created from a js_sys::Function()Called on initialization
updateJsValue created from a js_sys::Function(oldData)Called whenever the component’s properties change
tickJsValue created from a js_sys::Function(time, timeDelta)Called on each tick or frame of the scene’s render loop
tockJsValue created from a js_sys::Function(time, timeDelta, camera)Identical to the tick method but invoked after the scene has rendered
removeJsValue created from a js_sys::Function()Called whenever the component is detached from the entity
pauseJsValue created from a js_sys::Function()Called when the entity or scene pauses
playJsValue created from a js_sys::Function()Called when the entity or scene resumes
update_schemaJsValue created from a js_sys::Function(data)if defined, is called on every update in order to check if the schema needs to be dynamically modified

All parameteres are optional, although the order must be exactly as shown. dependencies should be a comma-separated list of strings followed by a semicolon. schema should be a HashMap with string keys and AframeProperty values. multiple is a boolean value. The rest are strings containing javascript code. A js! macro is provided to allow inline javascript code to be included in the Rust code (See the docs for the js! macro for caveats and limitations). Here’s an example:

// Example: 
let some_component = component_def!
(
    dependencies: "dependency1", "dependency2", some_string,
    schema: hashmap!
    {
        "position" => AframeProperty::float("number", None),
        "text" => AframeProperty::string("string", Some(Cow::Borrowed("x"))),
        "autoplay" => AframeProperty::boolean("boolean", Some(true))
    },
    multiple: true,
    init: js!
    (
        this.radians = Math.PI * 2; 
        this.initalRotation = this.el.object3D.rotation.clone();
    ),
    update: js!(oldData =>> this.rotation = this.el.object3D.rotation;),
    tick: js!
    (time, delta =>>
        if (this.data.autoplay)
        {
            var amount = this.data.radiansPerMillisecond * delta * this.data.speedMult;
            if (this.data.axis.includes('x'))
                this.rotation.x = (this.rotation.x + amount) % this.radians;
            if (this.data.axis.includes('y'))
                this.rotation.y = (this.rotation.y + amount) % this.radians;
            if (this.data.axis.includes('z'))
                this.rotation.z = (this.rotation.z + amount) % this.radians;
        }
    ),
    remove: js!(this.rotation.copy(this.initialRotation);),
    pause: js!(this.data.autoplay = false;),
    play: js!(this.data.autoplay = true;),
);
unsafe
{
    some_component.register("component_name");
}