diff --git a/meshroom/ui/qml/Viewer3D/MediaLibrary.qml b/meshroom/ui/qml/Viewer3D/MediaLibrary.qml index 9e02a99b..b06dbcfb 100644 --- a/meshroom/ui/qml/Viewer3D/MediaLibrary.qml +++ b/meshroom/ui/qml/Viewer3D/MediaLibrary.qml @@ -93,17 +93,18 @@ Entity { console.warn("Media Error: File " + pathStr + " does not exist.") return } - // file already loaded, return + // File already loaded, return if (m.sourceToEntity[pathStr]) { ensureVisible(pathStr) return } - // add file to the internal ListModel - m.mediaModel.append(makeElement({ - "source": pathStr, - "label": label ? label : Filepath.basename(pathStr), - "section": "External" + // Add file to the internal ListModel + m.mediaModel.append( + makeElement({ + "source": pathStr, + "label": label ? label : Filepath.basename(pathStr), + "section": "External" })) } @@ -115,16 +116,17 @@ Entity { var attrLabel = attribute.isOutput ? "" : attribute.fullName.replace(attribute.node.name, "") var section = attribute.node.label - // add file to the internal ListModel - m.mediaModel.append(makeElement({ + // Add file to the internal ListModel + m.mediaModel.append( + makeElement({ "label": section + attrLabel, "section": section, - "attribute": attribute, + "attribute": attribute })) } function remove(index) { - // remove corresponding entry from model + // Remove corresponding entry from model m.mediaModel.remove(index) } @@ -189,7 +191,7 @@ Entity { MediaLoader { id: mediaLoader - // whether MediaLoader has been fully instantiated by the NodeInstantiator + // Whether MediaLoader has been fully instantiated by the NodeInstantiator property bool fullyInstantiated: false // explicitly store some attached model properties for outside use and ease binding @@ -198,23 +200,23 @@ Entity { readonly property var modelSource: attribute || model.source readonly property bool visible: model.visible - // multi-step binding to ensure MediaLoader source is properly + // Multi-step binding to ensure MediaLoader source is properly // updated when needed, whether raw source is valid or not - // raw source path + // Raw source path property string rawSource: attribute ? attribute.value : model.source - // whether dependencies are statified (applies for output/connected input attributes only) + // Whether dependencies are statified (applies for output/connected input attributes only) readonly property bool dependencyReady: { if (attribute) { const rootAttribute = attribute.isLink ? attribute.rootLinkParam : attribute if (rootAttribute.isOutput) return rootAttribute.node.globalStatus === "SUCCESS" } - return true // is an input param without link (so no dependency) or an external file + return true // Is an input param without link (so no dependency) or an external file } - // source based on raw source + dependency status + // Source based on raw source + dependency status property string currentSource: dependencyReady ? rawSource : "" - // source based on currentSource + "requested" property + // Source based on currentSource + "requested" property property string finalSource: model.requested ? currentSource : "" // To use only if we want to draw the input source and not the current node output (Warning: to use with caution) @@ -229,14 +231,6 @@ Entity { renderMode: root.renderMode enabled: visible - // QObject.destroyed signal is not accessible - // Use the object as NodeInstantiator model to be notified of its deletion - NodeInstantiator { - model: attribute - delegate: Entity { objectName: "DestructionWatcher [" + model.toString() + "]" } - onObjectRemoved: remove(index) - } - property bool alive: attribute ? attribute.node.alive : false onAliveChanged: { if (!alive && index >= 0) @@ -245,19 +239,19 @@ Entity { // 'visible' property drives media loading request onVisibleChanged: { - // always request media loading if visible + // Always request media loading if visible if (model.visible) model.requested = true - // only cancel loading request if media is not valid + // Only cancel loading request if media is not valid // (a media won't be unloaded if already loaded, only hidden) else if (!model.valid) model.requested = false } function updateCacheAndModel(forceRequest) { - // don't cache explicitly unloaded media + // Don't cache explicitly unloaded media if (model.requested && object && dependencyReady) { - // cache current object + // Cache current object if (cache.add(Filepath.urlToString(mediaLoader.source), object)) object = null } @@ -265,21 +259,21 @@ Entity { } function updateModel(forceRequest) { - // update model's source path if input is an attribute + // Update model's source path if input is an attribute if (attribute) { model.source = rawSource } - // auto-restore entity if raw source is in cache + // Auto-restore entity if raw source is in cache model.requested = forceRequest || (!model.valid && model.requested) || cache.contains(rawSource) model.valid = Filepath.exists(rawSource) && dependencyReady } Component.onCompleted: { - // keep 'source' -> 'entity' reference + // Keep 'source' -> 'entity' reference m.sourceToEntity[modelSource] = instantiatedEntity - // always request media loading when delegate has been created + // Always request media loading when delegate has been created updateModel(true) - // if external media failed to open, remove element from model + // If external media failed to open, remove element from model if (!attribute && !object) remove(index) } @@ -293,7 +287,7 @@ Entity { } onFinalSourceChanged: { - // update media visibility + // Update media visibility // (useful if media was explicitly unloaded or hidden but loaded back from cache) model.visible = model.requested @@ -301,7 +295,7 @@ Entity { cached = cachedObject !== undefined if (cached) { object = cachedObject - // only change cached object parent if mediaLoader has been fully instantiated + // 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) { @@ -310,28 +304,28 @@ Entity { } mediaLoader.source = Filepath.stringToUrl(finalSource) if (object) { - // bind media info to corresponding model roles + // 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", "resectionIdCount", "resectionId", "resectionGroups"] boundProperties.forEach(function(prop) { model[prop] = Qt.binding(function() { return object ? object[prop] : 0 }) }) } else if (finalSource && status === Component.Ready) { - // source was valid but no loader was created, remove element - // check if component is ready to avoid removing element from the model before adding instance to the node + // Source was valid but no loader was created, remove element + // Check if component is ready to avoid removing element from the model before adding instance to the node remove(index) } } onFullyInstantiatedChanged: { - // delayed reparenting of object coming from the cache + // 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 + // Remove model entry for external media that failed to load if (status === SceneLoader.Error && !model.attribute) remove(index) } @@ -340,7 +334,7 @@ Entity { ObjectPicker { enabled: mediaLoader.enabled && pickingEnabled hoverEnabled: false - onPressed: root.pressed(pick) + onPressed: function(pick) { root.pressed(pick) } } ] } @@ -384,12 +378,12 @@ Entity { } } - onObjectAdded: { - // notify object that it is now fully instantiated + onObjectAdded: function(index, object) { + // Notify object that it is now fully instantiated object.fullyInstantiated = true } - onObjectRemoved: { + onObjectRemoved: function(index, object) { if (m.sourceToEntity[object.modelSource]) delete m.sourceToEntity[object.modelSource] }