mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-07-23 19:47:39 +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:
|
if extension is None:
|
||||||
extension = ".*"
|
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 bool loading: fetchButton.checked || m.playing
|
||||||
property alias settings_SequencePlayer: settings_SequencePlayer
|
property alias settings_SequencePlayer: settings_SequencePlayer
|
||||||
property alias frameId: m.frame
|
property alias frameId: m.frame
|
||||||
|
property var frameRange: {"min" : 0, "max" : sortedViewIds.length - 1}
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
id: settings_SequencePlayer
|
id: settings_SequencePlayer
|
||||||
|
@ -39,7 +40,7 @@ FloatingPane {
|
||||||
if (isOutputSequence)
|
if (isOutputSequence)
|
||||||
return
|
return
|
||||||
if (_reconstruction && m.frame >= 0 && m.frame < sortedViewIds.length) {
|
if (_reconstruction && m.frame >= 0 && m.frame < sortedViewIds.length) {
|
||||||
if (!m.playing && !frameSlider.pressed){
|
if (!m.playing && !frameSlider.pressed) {
|
||||||
_reconstruction.selectedViewId = sortedViewIds[m.frame];
|
_reconstruction.selectedViewId = sortedViewIds[m.frame];
|
||||||
} else {
|
} else {
|
||||||
_reconstruction.pickedViewId = sortedViewIds[m.frame];
|
_reconstruction.pickedViewId = sortedViewIds[m.frame];
|
||||||
|
@ -52,17 +53,22 @@ FloatingPane {
|
||||||
|
|
||||||
onIsOutputSequenceChanged: {
|
onIsOutputSequenceChanged: {
|
||||||
if (!isOutputSequence) {
|
if (!isOutputSequence) {
|
||||||
frameId = 0
|
frameId = frameRange.min
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSortedViewIdsChanged: {
|
||||||
|
frameSlider.from = frameRange.min
|
||||||
|
frameSlider.to = frameRange.max
|
||||||
|
}
|
||||||
|
|
||||||
// Sequence player model:
|
// Sequence player model:
|
||||||
// - current frame
|
// - current frame
|
||||||
// - data related to automatic sequence playing
|
// - data related to automatic sequence playing
|
||||||
QtObject {
|
QtObject {
|
||||||
id: m
|
id: m
|
||||||
|
|
||||||
property int frame: 0
|
property int frame: frameRange.min
|
||||||
property bool syncFeaturesSelected: true
|
property bool syncFeaturesSelected: true
|
||||||
property bool sync3DSelected: true
|
property bool sync3DSelected: true
|
||||||
property bool playing: false
|
property bool playing: false
|
||||||
|
@ -74,11 +80,10 @@ FloatingPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
onPlayingChanged: {
|
onPlayingChanged: {
|
||||||
if(!playing){
|
if (!playing) {
|
||||||
updateReconstructionView();
|
updateReconstructionView();
|
||||||
}else if(playing && (frame + 1 >= sortedViewIds.length))
|
} else if (playing && (frame + 1 >= frameRange + 1)) {
|
||||||
{
|
frame = frameRange.min;
|
||||||
frame = 0;
|
|
||||||
}
|
}
|
||||||
viewer.playback(playing);
|
viewer.playback(playing);
|
||||||
}
|
}
|
||||||
|
@ -113,9 +118,9 @@ FloatingPane {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let nextIndex = m.frame + 1;
|
let nextIndex = m.frame + 1;
|
||||||
if (nextIndex == sortedViewIds.length) {
|
if (nextIndex == frameRange.max + 1) {
|
||||||
if (m.repeat) {
|
if (m.repeat) {
|
||||||
m.frame = 0;
|
m.frame = frameRange.min;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -173,7 +178,7 @@ FloatingPane {
|
||||||
ToolTip.text: "Previous Frame"
|
ToolTip.text: "Previous Frame"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (m.frame > 0) {
|
if (m.frame > frameRange.min) {
|
||||||
m.frame -= 1;
|
m.frame -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +198,7 @@ FloatingPane {
|
||||||
onEditingFinished: {
|
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
|
// 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 = 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;
|
focus = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +217,7 @@ FloatingPane {
|
||||||
ToolTip.text: "Next Frame"
|
ToolTip.text: "Next Frame"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (m.frame < sortedViewIds.length - 1) {
|
if (m.frame < frameRange.max) {
|
||||||
m.frame += 1;
|
m.frame += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,8 +256,8 @@ FloatingPane {
|
||||||
snapMode: Slider.SnapAlways
|
snapMode: Slider.SnapAlways
|
||||||
live: true
|
live: true
|
||||||
|
|
||||||
from: 0
|
from: frameRange.min
|
||||||
to: sortedViewIds.length - 1
|
to: frameRange.max
|
||||||
|
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
m.frame = value;
|
m.frame = value;
|
||||||
|
@ -289,7 +294,7 @@ FloatingPane {
|
||||||
id: cacheView
|
id: cacheView
|
||||||
|
|
||||||
model: viewer ? viewer.cachedFrames : []
|
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 {
|
Rectangle {
|
||||||
x: modelData.x * cacheView.frameLength
|
x: modelData.x * cacheView.frameLength
|
||||||
|
|
|
@ -32,6 +32,7 @@ FocusScope {
|
||||||
readonly property alias sync3DSelected: sequencePlayer.sync3DSelected
|
readonly property alias sync3DSelected: sequencePlayer.sync3DSelected
|
||||||
property var sequence: []
|
property var sequence: []
|
||||||
property alias currentFrame: sequencePlayer.frameId
|
property alias currentFrame: sequencePlayer.frameId
|
||||||
|
property alias frameRange: sequencePlayer.frameRange
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: m
|
id: m
|
||||||
|
@ -228,6 +229,7 @@ FocusScope {
|
||||||
function getImageFile() {
|
function getImageFile() {
|
||||||
// Entry point for getting the image file URL
|
// Entry point for getting the image file URL
|
||||||
|
|
||||||
|
let attr = getAttributeByName(displayedNode, outputAttribute.name)
|
||||||
if (useExternal) {
|
if (useExternal) {
|
||||||
return sourceExternal
|
return sourceExternal
|
||||||
}
|
}
|
||||||
|
@ -238,8 +240,8 @@ FocusScope {
|
||||||
return Filepath.stringToUrl(path)
|
return Filepath.stringToUrl(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput) {
|
if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput && (attr.desc.semantic === "imageList" || attr.desc.semantic === "sequence")) {
|
||||||
var path = sequence[currentFrame]
|
var path = sequence[currentFrame-frameRange.min]
|
||||||
return Filepath.stringToUrl(path)
|
return Filepath.stringToUrl(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,12 +261,19 @@ FocusScope {
|
||||||
// ordered by path
|
// ordered by path
|
||||||
|
|
||||||
let objs = []
|
let objs = []
|
||||||
|
let attr = getAttributeByName(displayedNode, outputAttribute.name)
|
||||||
|
|
||||||
if (displayedNode && displayedNode.hasSequenceOutput) {
|
if (displayedNode && displayedNode.hasSequenceOutput && (attr.desc.semantic === "imageList" || attr.desc.semantic === "sequence")) {
|
||||||
currentFrame = 0
|
|
||||||
objs = Filepath.resolve(path_template, null)
|
objs = Filepath.resolve(path_template, null)
|
||||||
//order by path
|
//order by path
|
||||||
objs.sort()
|
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
|
return objs
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < _reconstruction.viewpoints.count; i++) {
|
for (let i = 0; i < _reconstruction.viewpoints.count; i++) {
|
||||||
|
@ -311,7 +320,7 @@ FocusScope {
|
||||||
// store attr name for output attributes that represent images
|
// store attr name for output attributes that represent images
|
||||||
for (var i = 0; i < displayedNode.attributes.count; i++) {
|
for (var i = 0; i < displayedNode.attributes.count; i++) {
|
||||||
var attr = displayedNode.attributes.at(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)
|
names.push(attr.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,7 +490,10 @@ FocusScope {
|
||||||
'cropFisheye': false,
|
'cropFisheye': false,
|
||||||
'sequence': Qt.binding(function() { return ((root.enableSequencePlayer && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput))) ? getSequence() : []) }),
|
'sequence': Qt.binding(function() { return ((root.enableSequencePlayer && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput))) ? getSequence() : []) }),
|
||||||
'targetSize': Qt.binding(function() { return floatImageViewerLoader.targetSize }),
|
'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 }),
|
'fetchingSequence': Qt.binding(function() { return sequencePlayer.loading }),
|
||||||
'memoryLimit': Qt.binding(function() { return sequencePlayer.settings_SequencePlayer.maxCacheMemory }),
|
'memoryLimit': Qt.binding(function() { return sequencePlayer.settings_SequencePlayer.maxCacheMemory }),
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue