From e6bf7e6e2da0a4893cc4bfd2a7664db192274a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 22 Aug 2023 11:04:37 +0200 Subject: [PATCH 1/2] [core] Add `validValue` and `errorMessage` support for ChoiceParams ChoiceParams can now also have their `validValue` and `errorMessage` parameters. The `validValueChanged` is also emitted whenever a parameter's value changes. This ensures that the `validValue` parameter is always re- evaluated when the attribute is updated, even if `validValue` itself does not change. --- meshroom/core/attribute.py | 1 + meshroom/core/desc.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/meshroom/core/attribute.py b/meshroom/core/attribute.py index 0c9bb563..2e6059ff 100644 --- a/meshroom/core/attribute.py +++ b/meshroom/core/attribute.py @@ -196,6 +196,7 @@ class Attribute(BaseObject): self.requestNodeUpdate() self.valueChanged.emit() + self.validValueChanged.emit() def upgradeValue(self, exportedValue): self._set_value(exportedValue) diff --git a/meshroom/core/desc.py b/meshroom/core/desc.py index 05d9478a..6d8cc2fa 100644 --- a/meshroom/core/desc.py +++ b/meshroom/core/desc.py @@ -303,13 +303,15 @@ class FloatParam(Param): class ChoiceParam(Param): """ """ - def __init__(self, name, label, description, value, values, exclusive, uid, group='allParams', joinChar=' ', advanced=False, semantic='', enabled=True): + def __init__(self, name, label, description, value, values, exclusive, uid, group='allParams', joinChar=' ', advanced=False, semantic='', + enabled=True, validValue=True, errorMessage=""): assert values self._values = values self._exclusive = exclusive self._joinChar = joinChar self._valueType = type(self._values[0]) # cast to value type - super(ChoiceParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, semantic=semantic, enabled=enabled) + super(ChoiceParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, + semantic=semantic, enabled=enabled, validValue=validValue, errorMessage=errorMessage) def conformValue(self, val): """ Conform 'val' to the correct type and check for its validity """ From 76d2e8680e508926fd67376b470fc2d30f4f6f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 22 Aug 2023 11:11:52 +0200 Subject: [PATCH 2/2] [nodes] KeyframeSelection: Flag `outputExtension` for video inputs If at least one of the inputs is a video, then the `outputExtension` attribute should never be set to "none": if it is, no frame will ever be written on disk, and as a consequence, no SfMData file will be written, meaning that the whole score computation and keyframe selection process will have been done for nothing. --- meshroom/nodes/aliceVision/KeyframeSelection.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meshroom/nodes/aliceVision/KeyframeSelection.py b/meshroom/nodes/aliceVision/KeyframeSelection.py index fcc2a6a7..a5ea1fe6 100644 --- a/meshroom/nodes/aliceVision/KeyframeSelection.py +++ b/meshroom/nodes/aliceVision/KeyframeSelection.py @@ -3,6 +3,9 @@ __version__ = "4.1" import os from meshroom.core import desc +# List of supported video extensions (provided by OpenImageIO) +videoExts = [".avi", ".mov", ".mp4", ".m4a", ".m4v", ".3gp", ".3g2", ".mj2", ".m4v", ".mpg"] + class KeyframeSelectionNodeSize(desc.DynamicNodeSize): def computeSize(self, node): inputPathsSize = super(KeyframeSelectionNodeSize, self).computeSize(node) @@ -273,6 +276,8 @@ You can extract frames at regular interval by configuring only the min/maxFrameS value="none", values=["none", "exr", "jpg", "png"], exclusive=True, + validValue=lambda node: not (any(ext in input.value.lower() for ext in videoExts for input in node.inputPaths.value) and node.outputExtension.value == "none"), + errorMessage="A video input has been provided. The output extension should be different from 'none'.", uid=[0], ), desc.ChoiceParam(