diff --git a/meshroom/core/node.py b/meshroom/core/node.py index c548f790ce..9b95b47b5b 100644 --- a/meshroom/core/node.py +++ b/meshroom/core/node.py @@ -20,8 +20,7 @@ from meshroom.core import desc, stats, hashValue, nodeVersion, Version from meshroom.core.attribute import attributeFactory, ListAttribute, GroupAttribute, Attribute from meshroom.core.exception import NodeUpgradeError, UnknownNodeTypeError -from meshroom.nodes.aliceVision.Meshing import boundingBoxMonitor - +from meshroom.core.nodes import getNodeClass def getWritingFilepath(filepath): return filepath + '.writing.' + str(uuid.uuid4()) @@ -1315,20 +1314,6 @@ def _updateChunks(self): else: self._chunks[0].range = desc.Range() -class MeshingNode(Node): - def __init__(self, nodeType, position=None, parent=None, **kwargs): - super().__init__(nodeType, position, parent, **kwargs) - self.internalFolderChanged.connect(self.checkBBox) - self.globalStatusChanged.connect(self.checkBBox) - - def checkBBox(self): - """Load automatic bounding box if needed.""" - if self.useBoundingBox.value: - return - self.automaticBBoxValid.value = False - with boundingBoxMonitor(self, checkOnce=True) as thread: - pass - class CompatibilityIssue(Enum): """ Enum describing compatibility issues when deserializing a Node. @@ -1569,8 +1554,8 @@ def upgrade(self): # store internal attributes that could be used during node upgrade commonInternalAttributes.append(attrName) - cl = MeshingNode if self.nodeType=="Meshing" else Node - node = cl(self.nodeType, position=self.position) + cls = getNodeClass(self.nodeType) + node = cls(self.nodeType, position=self.position) # convert attributes from a list of tuples into a dict attrValues = {key: value for (key, value) in self.inputs.items()} intAttrValues = {key: value for (key, value) in self.internalInputs.items()} @@ -1691,8 +1676,8 @@ def nodeFactory(nodeDict, name=None, template=False, uidConflict=False): break if compatibilityIssue is None: - cl = MeshingNode if nodeType=="Meshing" else Node - node = cl(nodeType, position, **inputs) + cls = getNodeClass(nodeType) + node = cls(nodeType, position, **inputs) node.setInternalAttributeValues(internalInputs) else: logging.warning("Compatibility issue detected for node '{}': {}".format(name, compatibilityIssue.name)) diff --git a/meshroom/core/nodes/MeshingNode.py b/meshroom/core/nodes/MeshingNode.py new file mode 100644 index 0000000000..2c135102e9 --- /dev/null +++ b/meshroom/core/nodes/MeshingNode.py @@ -0,0 +1,30 @@ +from meshroom.nodes.aliceVision.Meshing import boundingBoxMonitor +from meshroom.core.node import Node +from meshroom.common import Property, Signal + +class MeshingNode(Node): + def __init__(self, nodeType, position=None, parent=None, **kwargs): + super().__init__(nodeType, position, parent, **kwargs) + self.internalFolderChanged.connect(self.checkBBox) + self.globalStatusChanged.connect(self.checkBBox) + self._automaticBBoxValid = False + + @property + def automaticBBoxValid(self): + return self._automaticBBoxValid + + @automaticBBoxValid.setter + def automaticBBoxValid(self, value): + self._automaticBBoxValid = value + self.automaticBBoxValidChanged.emit() + + automaticBBoxValidChanged = Signal() + automaticBBoxValid = Property(bool, automaticBBoxValid.fget, automaticBBoxValid.fset, notify=automaticBBoxValidChanged) + + def checkBBox(self): + """Load automatic bounding box if needed.""" + if self.useBoundingBox.value: + return + self.automaticBBoxValid = False + with boundingBoxMonitor(self, checkOnce=True) as thread: + pass diff --git a/meshroom/core/nodes/__init__.py b/meshroom/core/nodes/__init__.py new file mode 100644 index 0000000000..e2050f262d --- /dev/null +++ b/meshroom/core/nodes/__init__.py @@ -0,0 +1,23 @@ +from typing import TYPE_CHECKING + +def getNodeClass(nodeType: str): + """ + Returns the appropriate subclass of `meshroom.core.node.Node` based on `nodeType`. + + Inputs + ------ + nodeType: str + the name of the node type + + Returns + ------- + type[Node] + the corresponding type class + """ + if nodeType=="Meshing": + from meshroom.core.nodes.MeshingNode import MeshingNode + cls = MeshingNode + else: + from meshroom.core.node import Node + cls = Node + return cls \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/Meshing.py b/meshroom/nodes/aliceVision/Meshing.py index 92fd9862e0..d661ce3f88 100644 --- a/meshroom/nodes/aliceVision/Meshing.py +++ b/meshroom/nodes/aliceVision/Meshing.py @@ -531,17 +531,6 @@ class Meshing(desc.AVCommandLineNode): value="{cache}/{nodeType}/{uid0}/densePointCloud.abc", uid=[], ), - desc.BoolParam( - name="automaticBBoxValid", - label="", - description="Indicates if the Bounding Box has been " - "automatically computed and loaded.\n" - "Note that this param is always not enabled (not exposed in the UI) and " - "only used to indicate if the automatic bounding box should be displayed.", - value=False, - enabled=False, - uid=[], - ), ] def processChunk(self, chunk): @@ -624,7 +613,7 @@ def updateBoundingBox(self) -> bool: for x in vec.value: x.value = data[i] i += 1 - self.node.automaticBBoxValid.value = True + self.node.automaticBBoxValid = True return True def stopRequest(self): diff --git a/meshroom/ui/qml/Viewer3D/MediaLibrary.qml b/meshroom/ui/qml/Viewer3D/MediaLibrary.qml index 524d5ba724..6edac0465f 100644 --- a/meshroom/ui/qml/Viewer3D/MediaLibrary.qml +++ b/meshroom/ui/qml/Viewer3D/MediaLibrary.qml @@ -167,8 +167,8 @@ Entity { property bool hasBoundingBox: { if(nodeType === "Meshing" && currentNode.attribute("useBoundingBox")) // Can have a BoundingBox { - if(currentNode.attribute("automaticBBoxValid")) - return currentNode.attribute("useBoundingBox").value || currentNode.attribute("automaticBBoxValid").value + if(currentNode.automaticBBoxValid !== undefined) + return currentNode.attribute("useBoundingBox").value || currentNode.automaticBBoxValid return currentNode.attribute("useBoundingBox").value } return false