import QtQuick 2.9 import Qt3D.Core 2.1 import Qt3D.Render 2.1 import Utils 1.0 /** * MediaLibrary is an Entity that loads and manages a list of 3D media. * It also uses an internal cache to instantly reload media. */ Entity { id: root readonly property alias model: m.mediaModel property int renderMode property bool pickingEnabled: false readonly property alias count: instantiator.count // number of instantiated media delegates /// Camera to consider for positionning property Camera camera: null /// True while at least one media is being loaded readonly property bool loading: { for(var i=0; i 'entity' reference m.sourceToEntity[modelSource] = mediaLoader; // always request media loading when delegate has been created updateModel(true); // if external media failed to open, remove element from model if(!attribute && !object) remove(index) } onCurrentSourceChanged: { updateCacheAndModel(false) } onFinalSourceChanged: { // update media visibility // (useful if media was explicitly unloaded or hidden but loaded back from cache) model.visible = model.requested; var cachedObject = cache.pop(rawSource); cached = cachedObject !== undefined; if(cached) { object = cachedObject; // only change cached object parent if mediaLoader has been fully instantiated // by the NodeInstantiator; otherwise re-parenting will fail silently and the object will disappear... // see "onFullyInstantiatedChanged" and parent NodeInstantiator's "onObjectAdded" if(fullyInstantiated) { object.parent = mediaLoader; } } mediaLoader.source = Filepath.stringToUrl(finalSource); if(object) { // bind media info to corresponding model roles // (test for object validity to avoid error messages right after object has been deleted) var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount"]; boundProperties.forEach( function(prop){ model[prop] = Qt.binding(function() { return object ? object[prop] : 0; }); }) } else if(finalSource) { // source was valid but no loader was created, remove element remove(index); } } onFullyInstantiatedChanged: { // delayed reparenting of object coming from the cache if(object) object.parent = mediaLoader; } onStatusChanged: { model.status = status // remove model entry for external media that failed to load if(status === SceneLoader.Error && !model.attribute) remove(index); } components: [ ObjectPicker { enabled: mediaLoader.enabled && pickingEnabled hoverEnabled: false onPressed: root.pressed(pick) } ] } onObjectAdded: { // notify object that it is now fully instantiated object.fullyInstantiated = true; } onObjectRemoved: { delete m.sourceToEntity[object.modelSource]; } } }