Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animate meshes #901

Merged
merged 5 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 206 additions & 1 deletion src/meshlab/layerDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,31 @@ LayerDialog::LayerDialog(QWidget *parent )
// The following connection is used to associate the click with the switch between raster and mesh view.
connect(ui->rasterTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem * , int )) , this, SLOT(rasterItemClicked(QTreeWidgetItem * , int ) ) );

// state buttons
// state and animation buttons
isRecording = false;
viewState[0] = viewState[1] = viewState[2] = viewState[3] = "";
connect(ui->bW1, SIGNAL(clicked()), this, SLOT(clickW1()));
connect(ui->bW2, SIGNAL(clicked()), this, SLOT(clickW2()));
connect(ui->bW3, SIGNAL(clicked()), this, SLOT(clickW3()));
connect(ui->bW4, SIGNAL(clicked()), this, SLOT(clickW4()));
connect(ui->animSlower, SIGNAL(clicked()), this, SLOT(clickAnimSlower()));
connect(ui->animStepBackward, SIGNAL(clicked()), this, SLOT(clickAnimStepBackward()));
connect(ui->animPlay, SIGNAL(clicked()), this, SLOT(clickAnimPlay()));
connect(ui->animStepForward, SIGNAL(clicked()), this, SLOT(clickAnimStepForward()));
connect(ui->animFaster, SIGNAL(clicked()), this, SLOT(clickAnimFaster()));
connect(ui->bV1, SIGNAL(clicked()), this, SLOT(clickV1()));
connect(ui->bV2, SIGNAL(clicked()), this, SLOT(clickV2()));
connect(ui->bV3, SIGNAL(clicked()), this, SLOT(clickV3()));
connect(ui->bV4, SIGNAL(clicked()), this, SLOT(clickV4()));

animIndex = -1;
animMsecDelay = 500;
animTimer = new QTimer(this);
resetAnim();
connect(animTimer, SIGNAL(timeout()), this, SLOT(updateAnim()));
// Make wide enough to accommodate alternate text ("||") from clickAnimPlay()
ui->animPlay->setMinimumSize(ui->animPlay->size().width() + 6, ui->animPlay->size().height());

this->setContextMenuPolicy(Qt::CustomContextMenu);
ui->meshTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
ui->rasterTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
Expand Down Expand Up @@ -219,6 +232,61 @@ void LayerDialog::clickW4()
mw->meshDoc()->Log.log(0, "No View to Restore");
}

void LayerDialog::clickAnimSlower()
{
if (animMsecDelay < 3000)
{
animMsecDelay = int(animMsecDelay * 1.2);
}
}

void LayerDialog::clickAnimStepBackward()
{
pauseAnim();
stepAnim(-1);
}

void LayerDialog::clickAnimPlay()
{
if (!animTimer->isActive() && startAnim())
{
ui->animPlay->setText(tr("||"));
ui->animPlay->setToolTip(tr("Pause animation"));
stepAnim(1);
animTimer->start(animMsecDelay);
}
else
{
pauseAnim();
}
}

void LayerDialog::clickAnimStepForward()
{
pauseAnim();
stepAnim(1);
}

void LayerDialog::clickAnimFaster()
{
if (animMsecDelay > 10)
{
animMsecDelay = int(animMsecDelay / 1.2f);
}
}

void LayerDialog::updateAnim()
{
if (stepAnim(1) > 1)
{
animTimer->start(animMsecDelay); // Restart in case animMsecDelay changed
}
else
{
pauseAnim();
}
}

void LayerDialog::clickV1()
{
MeshDocument *md = mw->meshDoc();
Expand Down Expand Up @@ -406,6 +474,13 @@ void LayerDialog::meshItemClicked (QTreeWidgetItem * item , int col)
mw->GLA()->meshSetVisibility(*md->getMesh(clickedId), !md->getMesh(clickedId)->isVisible());
}
updatePerMeshItemVisibility();

// If not animating, or a mesh in the animation set was clicked, reset the animation
if (!ui->animPlay->isChecked() ||
std::find(animMeshIDs.begin(), animMeshIDs.end(), clickedId) != animMeshIDs.end())
{
resetAnim();
}
} break;
case 1 :

Expand Down Expand Up @@ -676,6 +751,28 @@ void LayerDialog::updateTable(const MLSceneGLSharedDataContext::PerMeshRendering
}
_docitem->addChildren(itms);

// Delete any animation IDs no longer in the layer dialog
for (auto animIter = animMeshIDs.begin(); animIter != animMeshIDs.end(); )
{
bool foundInMeshList = false;
for(MeshModel& m : md->meshIterator())
{
if (m.id() == *animIter)
{
foundInMeshList = true;
break;
}
}
if (foundInMeshList)
{
++animIter;
}
else
{
animIter = animMeshIDs.erase(animIter);
}
}

updateTreeWidgetSizes(ui->meshTreeWidget);
updatePerMeshItemVisibility();
updatePerMeshItemSelectionStatus();
Expand Down Expand Up @@ -861,6 +958,114 @@ void LayerDialog::actionActivated(MLRenderingAction* ract)
_tabw->switchTab(ract->meshId(),ract->text());
}

bool LayerDialog::startAnim()
{
if (animMeshIDs.size() > 1)
{
return true;
}

MeshDocument *md = mw->meshDoc();
bool canAnimate = md->meshNumber() > 1;

if (canAnimate)
{
int visibleCount = 0;
for(MeshModel& m : md->meshIterator())
{
if (m.isVisible())
{
++visibleCount;
}
}
// If fewer than two meshes were visible select all meshes, else select only the visible ones
animIndex = -1;
animMeshIDs.clear();
for(MeshModel& m : md->meshIterator())
{
if (m.isVisible() && animIndex < 0)
{
animIndex = animMeshIDs.size(); // Remember first visible mesh
}
if (m.isVisible() || visibleCount < 2)
{
animMeshIDs.push_back(m.id());
}
}
if (animIndex >= 0)
{
--animIndex;
}
ui->animStepBackward->setEnabled(true);
ui->animStepForward->setEnabled(true);
}
return canAnimate;
}

// Advance the animation by the specified offset (1 = forward, -1 = backward)
int LayerDialog::stepAnim(int offset)
{
bool foundVisible = false;
int animatingCount = 0;
MeshDocument *md = mw->meshDoc();

if (md->meshNumber() > 1)
{
MeshModel* lastMP = nullptr;

while (!foundVisible && animMeshIDs.size() > 1)
{
animIndex = (animMeshIDs.size() + animIndex + offset) % animMeshIDs.size();
animatingCount = 0;
for (const auto& id : animMeshIDs)
{
for(MeshModel& m : md->meshIterator())
{
if (m.id() == id)
{
bool makeVisible = m.id() == animMeshIDs[animIndex];
mw->GLA()->meshSetVisibility(m, makeVisible);
foundVisible |= makeVisible;
++animatingCount;
lastMP = &m;
}
}
}
if (!foundVisible)
{
// The mesh being animated to was deleted; remove it from the list and try again
animMeshIDs.erase(animMeshIDs.begin() + animIndex);
animIndex -= offset;
}
}
if (animMeshIDs.size() == 1 && lastMP != nullptr)
{
mw->GLA()->meshSetVisibility(*lastMP, true);
}
updatePerMeshItemVisibility();
updatePerMeshItemSelectionStatus();
mw->GLA()->update();
}
return animatingCount;
}

void LayerDialog::pauseAnim()
{
animTimer->stop();
ui->animPlay->setChecked(false);
ui->animPlay->setText(tr(">"));
ui->animPlay->setToolTip(tr("Resume animation"));
}

void LayerDialog::resetAnim()
{
pauseAnim();
animMeshIDs.clear();
ui->animStepBackward->setEnabled(false);
ui->animStepForward->setEnabled(false);
ui->animPlay->setToolTip(tr("Animate visible meshes, or all if < 2 are visible"));
}

LayerDialog::~LayerDialog()
{
delete ui;
Expand Down
17 changes: 17 additions & 0 deletions src/meshlab/layerDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <QTabWidget>
#include <QGroupBox>
#include <QCheckBox>
#include <QTimer>
#include <common/parameters/rich_parameter_list.h>
#include <common/ml_shared_data_context/ml_shared_data_context.h>
#include "ml_render_gui.h"
Expand Down Expand Up @@ -140,6 +141,12 @@ public slots:
void clickW2();
void clickW3();
void clickW4();
void clickAnimSlower();
void clickAnimStepBackward();
void clickAnimPlay();
void clickAnimStepForward();
void clickAnimFaster();
void updateAnim();
void clickV1();
void clickV2();
void clickV3();
Expand Down Expand Up @@ -177,6 +184,16 @@ private slots:
QString viewState[4];
QMap<int, bool> visibilityState[4];

int animIndex;
std::vector<int> animMeshIDs;
int animMsecDelay;
QTimer* animTimer;

bool startAnim();
int stepAnim(int offset);
void pauseAnim();
void resetAnim();

QTreeWidgetItem* _docitem;
int _previd;
QGroupBox* _renderingtabcontainer;
Expand Down
100 changes: 99 additions & 1 deletion src/meshlab/ui/layerDialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,105 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="animSlower">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>Decrease animation speed</string>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="animStepBackward">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>Animate one step backward</string>
</property>
<property name="text">
<string>-1</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="animPlay">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&gt;</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="animStepForward">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>Animate one step forward</string>
</property>
<property name="text">
<string>+1</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="animFaster">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>Increase animation speed</string>
</property>
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
Expand Down