mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-01 07:48:37 +02:00
[ui] Support for imageList and sequence in SequencePlayer
This commit is contained in:
parent
7af0997a73
commit
4590868317
3 changed files with 39 additions and 22 deletions
|
@ -144,4 +144,4 @@ class FilepathHelper(QObject):
|
|||
"""
|
||||
if extension is None:
|
||||
extension = ".*"
|
||||
return [self.removeExtension(FilepathHelper, self.basename(FilepathHelper, f)) for f in glob.glob(os.path.join(folderPath, f"*{extension}")) if os.path.isfile(f)]
|
||||
return [self.basename(FilepathHelper, f) for f in glob.glob(os.path.join(folderPath, f"*{extension}")) if os.path.isfile(f)]
|
||||
|
|
|
@ -29,6 +29,7 @@ FloatingPane {
|
|||
property bool loading: fetchButton.checked || m.playing
|
||||
property alias settings_SequencePlayer: settings_SequencePlayer
|
||||
property alias frameId: m.frame
|
||||
property var frameRange: {"min" : 0, "max" : sortedViewIds.length - 1}
|
||||
|
||||
Settings {
|
||||
id: settings_SequencePlayer
|
||||
|
@ -52,17 +53,22 @@ FloatingPane {
|
|||
|
||||
onIsOutputSequenceChanged: {
|
||||
if (!isOutputSequence) {
|
||||
frameId = 0
|
||||
frameId = frameRange.min
|
||||
}
|
||||
}
|
||||
|
||||
onSortedViewIdsChanged: {
|
||||
frameSlider.from = frameRange.min
|
||||
frameSlider.to = frameRange.max
|
||||
}
|
||||
|
||||
// Sequence player model:
|
||||
// - current frame
|
||||
// - data related to automatic sequence playing
|
||||
QtObject {
|
||||
id: m
|
||||
|
||||
property int frame: 0
|
||||
property int frame: frameRange.min
|
||||
property bool syncFeaturesSelected: true
|
||||
property bool sync3DSelected: true
|
||||
property bool playing: false
|
||||
|
@ -76,9 +82,8 @@ FloatingPane {
|
|||
onPlayingChanged: {
|
||||
if (!playing) {
|
||||
updateReconstructionView();
|
||||
}else if(playing && (frame + 1 >= sortedViewIds.length))
|
||||
{
|
||||
frame = 0;
|
||||
} else if (playing && (frame + 1 >= frameRange + 1)) {
|
||||
frame = frameRange.min;
|
||||
}
|
||||
viewer.playback(playing);
|
||||
}
|
||||
|
@ -113,9 +118,9 @@ FloatingPane {
|
|||
return;
|
||||
}
|
||||
let nextIndex = m.frame + 1;
|
||||
if (nextIndex == sortedViewIds.length) {
|
||||
if (nextIndex == frameRange.max + 1) {
|
||||
if (m.repeat) {
|
||||
m.frame = 0;
|
||||
m.frame = frameRange.min;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -173,7 +178,7 @@ FloatingPane {
|
|||
ToolTip.text: "Previous Frame"
|
||||
|
||||
onClicked: {
|
||||
if (m.frame > 0) {
|
||||
if (m.frame > frameRange.min) {
|
||||
m.frame -= 1;
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +198,7 @@ FloatingPane {
|
|||
onEditingFinished: {
|
||||
// We first assign the frame to the entered text even if it is an invalid frame number. We do it for extreme cases, for example without doing it, if we are at 0, and put a negative number, m.frame would be still 0 and nothing happens but we will still see the wrong number
|
||||
m.frame = parseInt(text)
|
||||
m.frame = Math.min((sortedViewIds.length - 1), Math.max(0, parseInt(text)));
|
||||
m.frame = Math.min(frameRange.max, Math.max(frameRange.min, parseInt(text)));
|
||||
focus = false;
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +217,7 @@ FloatingPane {
|
|||
ToolTip.text: "Next Frame"
|
||||
|
||||
onClicked: {
|
||||
if (m.frame < sortedViewIds.length - 1) {
|
||||
if (m.frame < frameRange.max) {
|
||||
m.frame += 1;
|
||||
}
|
||||
}
|
||||
|
@ -251,8 +256,8 @@ FloatingPane {
|
|||
snapMode: Slider.SnapAlways
|
||||
live: true
|
||||
|
||||
from: 0
|
||||
to: sortedViewIds.length - 1
|
||||
from: frameRange.min
|
||||
to: frameRange.max
|
||||
|
||||
onValueChanged: {
|
||||
m.frame = value;
|
||||
|
@ -289,7 +294,7 @@ FloatingPane {
|
|||
id: cacheView
|
||||
|
||||
model: viewer ? viewer.cachedFrames : []
|
||||
property real frameLength: sortedViewIds.length > 0 ? frameSlider.width / sortedViewIds.length : 0
|
||||
property real frameLength: sortedViewIds.length > 0 ? frameSlider.width / (frameRange.max-frameRange.min+1) : 0
|
||||
|
||||
Rectangle {
|
||||
x: modelData.x * cacheView.frameLength
|
||||
|
|
|
@ -32,6 +32,7 @@ FocusScope {
|
|||
readonly property alias sync3DSelected: sequencePlayer.sync3DSelected
|
||||
property var sequence: []
|
||||
property alias currentFrame: sequencePlayer.frameId
|
||||
property alias frameRange: sequencePlayer.frameRange
|
||||
|
||||
QtObject {
|
||||
id: m
|
||||
|
@ -228,6 +229,7 @@ FocusScope {
|
|||
function getImageFile() {
|
||||
// Entry point for getting the image file URL
|
||||
|
||||
let attr = getAttributeByName(displayedNode, outputAttribute.name)
|
||||
if (useExternal) {
|
||||
return sourceExternal
|
||||
}
|
||||
|
@ -238,8 +240,8 @@ FocusScope {
|
|||
return Filepath.stringToUrl(path)
|
||||
}
|
||||
|
||||
if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput) {
|
||||
var path = sequence[currentFrame]
|
||||
if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput && (attr.desc.semantic === "imageList" || attr.desc.semantic === "sequence")) {
|
||||
var path = sequence[currentFrame-frameRange.min]
|
||||
return Filepath.stringToUrl(path)
|
||||
}
|
||||
|
||||
|
@ -259,12 +261,19 @@ FocusScope {
|
|||
// ordered by path
|
||||
|
||||
let objs = []
|
||||
let attr = getAttributeByName(displayedNode, outputAttribute.name)
|
||||
|
||||
if (displayedNode && displayedNode.hasSequenceOutput) {
|
||||
currentFrame = 0
|
||||
if (displayedNode && displayedNode.hasSequenceOutput && (attr.desc.semantic === "imageList" || attr.desc.semantic === "sequence")) {
|
||||
objs = Filepath.resolve(path_template, null)
|
||||
//order by path
|
||||
objs.sort()
|
||||
// reset current frame to 0 if it is imageList but not sequence
|
||||
if (attr.desc.semantic === "imageList")
|
||||
frameRange.min = 0
|
||||
frameRange.max = objs.length-1
|
||||
currentFrame = 0
|
||||
if (attr.desc.semantic === "sequence")
|
||||
currentFrame = frameRange.min
|
||||
return objs
|
||||
} else {
|
||||
for (let i = 0; i < _reconstruction.viewpoints.count; i++) {
|
||||
|
@ -311,7 +320,7 @@ FocusScope {
|
|||
// store attr name for output attributes that represent images
|
||||
for (var i = 0; i < displayedNode.attributes.count; i++) {
|
||||
var attr = displayedNode.attributes.at(i)
|
||||
if (attr.isOutput && (attr.desc.semantic === "image" || attr.desc.semantic === "sequence") && attr.enabled) {
|
||||
if (attr.isOutput && (attr.desc.semantic === "image" || attr.desc.semantic === "sequence" || attr.desc.semantic === "imageList") && attr.enabled) {
|
||||
names.push(attr.name)
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +490,10 @@ FocusScope {
|
|||
'cropFisheye': false,
|
||||
'sequence': Qt.binding(function() { return ((root.enableSequencePlayer && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput))) ? getSequence() : []) }),
|
||||
'targetSize': Qt.binding(function() { return floatImageViewerLoader.targetSize }),
|
||||
'useSequence': Qt.binding(function() { return (root.enableSequencePlayer && !useExternal && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput))) }),
|
||||
'useSequence': Qt.binding(function() {
|
||||
let attr = getAttributeByName(root.displayedNode, outputAttribute.name)
|
||||
return (root.enableSequencePlayer && !useExternal && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput)) && (attr.desc.semantic === "imageList" || attr.desc.semantic === "sequence"))
|
||||
}),
|
||||
'fetchingSequence': Qt.binding(function() { return sequencePlayer.loading }),
|
||||
'memoryLimit': Qt.binding(function() { return sequencePlayer.settings_SequencePlayer.maxCacheMemory }),
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue