Search code examples
aframe

How does the asset schema property work with img assets?


I am trying to pass an image as an asset property type to some other component (so that either a #selector or a url(url) can be passed) but it seems to take in the entire html component, instead of just the url.

<!DOCTYPE html>
<html>
    <head>
    <title>Hello, WebVR! - A-Frame</title>
    <meta name='description' content='Hello, WebVR! - A-Frame'>
    <script src='../../global/js/aframe-v0.8.0.min.js'></script>

    <script>
        AFRAME.registerComponent('some-component', {
            schema: {
                image:  {type:'asset',      default:''},
                model:  {type:'asset',      default:''}
            },
            init: function() {
                console.log(this.data.image);   //prints out <img id="SomeImage" src="../../someDir/someFile.jpg">
                console.log(this.data.model);   //prints out '../../someDir/someModel.gltf'
            }
        });
    </script>
    </head>
    <body>
    <a-scene >
        <a-assets timeout='3000'>
            <!-- this works as an asset no problem -->
            <a-asset-item id='SomeModel' src='../../global/assets/models/gltf/UserHead/UserHead.gltf'></a-asset-item>

            <!-- this does not pass as an asset but rather an html element -->
            <img id='SomeImage' src='../../global/assets/textures/equirectangular/CloudySky.jpg'>
        </a-assets>

        <a-entity some-component='image:#SomeImage; model:#SomeModel;'></a-entity>
    </a-scene>
    </body>
</html>

Thought I might look to see how A-Frame handles this in the material component can't see where does the 'src' property on material come from?

<a-entity id='skyBox'
            geometry='primitive:sphere; radius:50; segments-height:6; segments-width:6;'
            material='shader:flat; src:#skyMap; side:back; height:2048; width:2048'>
</a-entity>

Material component (can't see src): https://github.com/aframevr/aframe/blob/master/src/components/material.js

Thanks!

EDIT:

As per Piotr's discoveries below it looks like images are handed as a special case, as can be in the src code here with frame 0.8.0 where an image source is handed like this:

hash: function (data) {
    if (data.src.tagName) {
        // Since `data.src` can be an element, parse out the string if necessary for the hash.
        data = utils.extendDeep({}, data);
        data.src = data.src.src;
    }
    return JSON.stringify(data);
},

So basically if an image we the asset property will not handle image's properly and an additional step of grabbing the url from it via

data.src.src

OR

data.src.getAttribute('src');

Solution

  • Please correct me if i'm wrong, but i think it's not in the material schema.

    I think the devil's in the component.js, which not only seems to allow you to assign a value to any given property, but also has the constructor for any component, and parses the schema.

    That being said, the material does not need a src in the schema, as it seems to be a part of every component. Furthermore there are multiple parsers like the assetParse, or src-loader, checking whether an attribute is a html element, or even a video / image asset.


    As for the material part, check out the dist source code, where I think what you're looking for is:

    module.exports.updateMapMaterialFromData
    

    where you can see a-frame team uses the data.src for the material, and updates the texture with it. Just give it a ctrl+F (only 3 hits).


    So when

    module.exports.updateMapMaterialFromData('map', 'src', shader, data);
    

    is called, with the given definition:

    module.exports.updateMapMaterialFromData = function (materialName, dataName, shader, data) {
      var el = shader.el;
      var material = shader.material;
      var src = data[dataName];
      .......
    

    makes src = data[src] => they make updates using a local variable src.


    Also you can see the src-loader in action where the material system is registered, and when a src attribute is found out, the validateSrc function fires one of the two callbacks:

    utils.srcLoader.validateSrc(src, loadImageCb, loadVideoCb);