Add tool button tips especially when failed to generate mesh #20

This commit add tips for buttons, to show what the function of the button.
Also, fixed a issue, there was no useful infos to tell user when the mesh was failed to generate, now user should see a warning icon with tips to show why the preview disappear.

Thanks the following contributors:
@RubenSandwich <https://github.com/RubenSandwich>
boynet <https://dust3d.discourse.group/u/boynet>
fornclake <https://www.reddit.com/user/fornclake>
master
Jeremy Hu 2019-01-07 22:33:42 +09:30
parent 2bbb222e02
commit b65205a48c
8 changed files with 65 additions and 5 deletions

View File

@ -35,6 +35,7 @@ Document::Document() :
m_isResultMeshObsolete(false), m_isResultMeshObsolete(false),
m_meshGenerator(nullptr), m_meshGenerator(nullptr),
m_resultMesh(nullptr), m_resultMesh(nullptr),
m_isMeshGenerationSucceed(true),
m_batchChangeRefCount(0), m_batchChangeRefCount(0),
m_currentOutcome(nullptr), m_currentOutcome(nullptr),
m_isTextureObsolete(false), m_isTextureObsolete(false),
@ -1355,6 +1356,11 @@ MeshLoader *Document::takeResultMesh()
return resultMesh; return resultMesh;
} }
bool Document::isMeshGenerationSucceed()
{
return m_isMeshGenerationSucceed;
}
MeshLoader *Document::takeResultTextureMesh() MeshLoader *Document::takeResultTextureMesh()
{ {
if (nullptr == m_resultTextureMesh) if (nullptr == m_resultTextureMesh)
@ -1375,6 +1381,7 @@ void Document::meshReady()
{ {
MeshLoader *resultMesh = m_meshGenerator->takeResultMesh(); MeshLoader *resultMesh = m_meshGenerator->takeResultMesh();
Outcome *outcome = m_meshGenerator->takeOutcome(); Outcome *outcome = m_meshGenerator->takeOutcome();
bool isSucceed = m_meshGenerator->isSucceed();
for (auto &partId: m_meshGenerator->generatedPreviewPartIds()) { for (auto &partId: m_meshGenerator->generatedPreviewPartIds()) {
auto part = partMap.find(partId); auto part = partMap.find(partId);
@ -1388,6 +1395,8 @@ void Document::meshReady()
delete m_resultMesh; delete m_resultMesh;
m_resultMesh = resultMesh; m_resultMesh = resultMesh;
m_isMeshGenerationSucceed = isSucceed;
delete m_currentOutcome; delete m_currentOutcome;
m_currentOutcome = outcome; m_currentOutcome = outcome;

View File

@ -491,6 +491,7 @@ public:
const Pose *findPose(QUuid poseId) const; const Pose *findPose(QUuid poseId) const;
const Motion *findMotion(QUuid motionId) const; const Motion *findMotion(QUuid motionId) const;
MeshLoader *takeResultMesh(); MeshLoader *takeResultMesh();
bool isMeshGenerationSucceed();
MeshLoader *takeResultTextureMesh(); MeshLoader *takeResultTextureMesh();
MeshLoader *takeResultRigWeightMesh(); MeshLoader *takeResultRigWeightMesh();
const std::vector<RiggerBone> *resultRigBones() const; const std::vector<RiggerBone> *resultRigBones() const;
@ -630,6 +631,7 @@ private: // need initialize
bool m_isResultMeshObsolete; bool m_isResultMeshObsolete;
MeshGenerator *m_meshGenerator; MeshGenerator *m_meshGenerator;
MeshLoader *m_resultMesh; MeshLoader *m_resultMesh;
bool m_isMeshGenerationSucceed;
int m_batchChangeRefCount; int m_batchChangeRefCount;
Outcome *m_currentOutcome; Outcome *m_currentOutcome;
bool m_isTextureObsolete; bool m_isTextureObsolete;

View File

@ -104,7 +104,8 @@ DocumentWindow::DocumentWindow() :
m_firstShow(true), m_firstShow(true),
m_documentSaved(true), m_documentSaved(true),
m_exportPreviewWidget(nullptr), m_exportPreviewWidget(nullptr),
m_advanceSettingWidget(nullptr) m_advanceSettingWidget(nullptr),
m_isLastMeshGenerationSucceed(true)
{ {
if (!g_logBrowser) { if (!g_logBrowser) {
g_logBrowser = new LogBrowser; g_logBrowser = new LogBrowser;
@ -120,47 +121,71 @@ DocumentWindow::DocumentWindow() :
toolButtonLayout->setContentsMargins(5, 10, 4, 0); toolButtonLayout->setContentsMargins(5, 10, 4, 0);
QPushButton *addButton = new QPushButton(QChar(fa::plus)); QPushButton *addButton = new QPushButton(QChar(fa::plus));
addButton->setToolTip(tr("Add node to canvas"));
Theme::initAwesomeButton(addButton); Theme::initAwesomeButton(addButton);
QPushButton *selectButton = new QPushButton(QChar(fa::mousepointer)); QPushButton *selectButton = new QPushButton(QChar(fa::mousepointer));
selectButton->setToolTip(tr("Select node on canvas"));
Theme::initAwesomeButton(selectButton); Theme::initAwesomeButton(selectButton);
QPushButton *dragButton = new QPushButton(QChar(fa::handrocko)); QPushButton *dragButton = new QPushButton(QChar(fa::handrocko));
dragButton->setToolTip(tr("Enter drag mode"));
Theme::initAwesomeButton(dragButton); Theme::initAwesomeButton(dragButton);
QPushButton *zoomInButton = new QPushButton(QChar(fa::searchplus)); QPushButton *zoomInButton = new QPushButton(QChar(fa::searchplus));
zoomInButton->setToolTip(tr("Enter zoom in mode"));
Theme::initAwesomeButton(zoomInButton); Theme::initAwesomeButton(zoomInButton);
QPushButton *zoomOutButton = new QPushButton(QChar(fa::searchminus)); QPushButton *zoomOutButton = new QPushButton(QChar(fa::searchminus));
zoomOutButton->setToolTip(tr("Enter zoom out mode"));
Theme::initAwesomeButton(zoomOutButton); Theme::initAwesomeButton(zoomOutButton);
m_xlockButton = new QPushButton(QChar('X')); m_xlockButton = new QPushButton(QChar('X'));
m_xlockButton->setToolTip(tr("X axis locker"));
initLockButton(m_xlockButton); initLockButton(m_xlockButton);
updateXlockButtonState(); updateXlockButtonState();
m_ylockButton = new QPushButton(QChar('Y')); m_ylockButton = new QPushButton(QChar('Y'));
m_ylockButton->setToolTip(tr("Y axis locker"));
initLockButton(m_ylockButton); initLockButton(m_ylockButton);
updateYlockButtonState(); updateYlockButtonState();
m_zlockButton = new QPushButton(QChar('Z')); m_zlockButton = new QPushButton(QChar('Z'));
m_zlockButton->setToolTip(tr("Z axis locker"));
initLockButton(m_zlockButton); initLockButton(m_zlockButton);
updateZlockButtonState(); updateZlockButtonState();
m_radiusLockButton = new QPushButton(QChar(fa::bullseye)); m_radiusLockButton = new QPushButton(QChar(fa::bullseye));
m_radiusLockButton->setToolTip(tr("Node radius locker"));
Theme::initAwesomeButton(m_radiusLockButton); Theme::initAwesomeButton(m_radiusLockButton);
updateRadiusLockButtonState(); updateRadiusLockButtonState();
QPushButton *rotateCounterclockwiseButton = new QPushButton(QChar(fa::rotateleft)); QPushButton *rotateCounterclockwiseButton = new QPushButton(QChar(fa::rotateleft));
rotateCounterclockwiseButton->setToolTip(tr("Rotate whole model (CCW)"));
Theme::initAwesomeButton(rotateCounterclockwiseButton); Theme::initAwesomeButton(rotateCounterclockwiseButton);
QPushButton *rotateClockwiseButton = new QPushButton(QChar(fa::rotateright)); QPushButton *rotateClockwiseButton = new QPushButton(QChar(fa::rotateright));
rotateClockwiseButton->setToolTip(tr("Rotate whole model"));
Theme::initAwesomeButton(rotateClockwiseButton); Theme::initAwesomeButton(rotateClockwiseButton);
auto updateRegenerateIconAndTips = [&](SpinnableAwesomeButton *regenerateButton, bool isSucceed, bool forceUpdate=false) {
if (!forceUpdate) {
if (m_isLastMeshGenerationSucceed == isSucceed)
return;
}
m_isLastMeshGenerationSucceed = isSucceed;
regenerateButton->setToolTip(m_isLastMeshGenerationSucceed ? tr("Regenerate") : tr("Mesh generation failed, please undo or adjust recent changed nodes\nTips:\n - Don't let generated mesh self-intersect\n - Make multiple parts instead of one single part for whole model"));
regenerateButton->setAwesomeIcon(m_isLastMeshGenerationSucceed ? QChar(fa::recycle) : QChar(fa::warning));
};
SpinnableAwesomeButton *regenerateButton = new SpinnableAwesomeButton(); SpinnableAwesomeButton *regenerateButton = new SpinnableAwesomeButton();
regenerateButton->setAwesomeIcon(QChar(fa::recycle)); updateRegenerateIconAndTips(regenerateButton, m_isLastMeshGenerationSucceed, true);
connect(m_document, &Document::meshGenerating, this, [=]() { connect(m_document, &Document::meshGenerating, this, [=]() {
regenerateButton->showSpinner(true); regenerateButton->showSpinner(true);
}); });
connect(m_document, &Document::resultMeshChanged, this, [=]() {
updateRegenerateIconAndTips(regenerateButton, m_document->isMeshGenerationSucceed());
});
connect(m_document, &Document::postProcessing, this, [=]() { connect(m_document, &Document::postProcessing, this, [=]() {
regenerateButton->showSpinner(true); regenerateButton->showSpinner(true);
}); });

View File

@ -72,6 +72,7 @@ private:
ExportPreviewWidget *m_exportPreviewWidget; ExportPreviewWidget *m_exportPreviewWidget;
AdvanceSettingWidget *m_advanceSettingWidget; AdvanceSettingWidget *m_advanceSettingWidget;
std::vector<QWidget *> m_dialogs; std::vector<QWidget *> m_dialogs;
bool m_isLastMeshGenerationSucceed;
private: private:
QString m_currentFilename; QString m_currentFilename;

View File

@ -25,8 +25,8 @@ int main(int argc, char ** argv)
darkPalette.setColor(QPalette::WindowText, Theme::white); darkPalette.setColor(QPalette::WindowText, Theme::white);
darkPalette.setColor(QPalette::Base, QColor(25,25,25)); darkPalette.setColor(QPalette::Base, QColor(25,25,25));
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53)); darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
darkPalette.setColor(QPalette::ToolTipBase, Theme::white); //darkPalette.setColor(QPalette::ToolTipBase, Theme::white);
darkPalette.setColor(QPalette::ToolTipText, Theme::white); //darkPalette.setColor(QPalette::ToolTipText, Theme::white);
darkPalette.setColor(QPalette::Text, Theme::white); darkPalette.setColor(QPalette::Text, Theme::white);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, Theme::black); darkPalette.setColor(QPalette::Disabled, QPalette::Text, Theme::black);
darkPalette.setColor(QPalette::Button, QColor(53,53,53)); darkPalette.setColor(QPalette::Button, QColor(53,53,53));
@ -36,7 +36,7 @@ int main(int argc, char ** argv)
darkPalette.setColor(QPalette::Highlight, Theme::red); darkPalette.setColor(QPalette::Highlight, Theme::red);
darkPalette.setColor(QPalette::HighlightedText, Theme::black); darkPalette.setColor(QPalette::HighlightedText, Theme::black);
qApp->setPalette(darkPalette); qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #fc6621; border: 1px solid white; }"); //qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #fc6621; border: 1px solid white; }");
QCoreApplication::setApplicationName(APP_NAME); QCoreApplication::setApplicationName(APP_NAME);

View File

@ -36,6 +36,7 @@ void GeneratedCacheContext::updateComponentCombinableMesh(QString componentId, v
MeshGenerator::MeshGenerator(Snapshot *snapshot) : MeshGenerator::MeshGenerator(Snapshot *snapshot) :
m_snapshot(snapshot), m_snapshot(snapshot),
m_isSucceed(false),
m_mesh(nullptr), m_mesh(nullptr),
m_outcome(nullptr), m_outcome(nullptr),
m_sharedContextWidget(nullptr), m_sharedContextWidget(nullptr),
@ -81,6 +82,11 @@ void MeshGenerator::setSharedContextWidget(QOpenGLWidget *widget)
m_sharedContextWidget = widget; m_sharedContextWidget = widget;
} }
bool MeshGenerator::isSucceed()
{
return m_isSucceed;
}
MeshLoader *MeshGenerator::takeResultMesh() MeshLoader *MeshGenerator::takeResultMesh()
{ {
MeshLoader *resultMesh = m_mesh; MeshLoader *resultMesh = m_mesh;
@ -697,6 +703,10 @@ void *MeshGenerator::combineComponentMesh(QString componentId, CombineMode *comb
cachedComponentPositions.clear(); cachedComponentPositions.clear();
loadCombinableMeshVerticesPositions(resultMesh, cachedComponentPositions); loadCombinableMeshVerticesPositions(resultMesh, cachedComponentPositions);
if (nullptr == resultMesh) {
m_isSucceed = false;
}
return resultMesh; return resultMesh;
} }
@ -707,6 +717,8 @@ void MeshGenerator::generate()
QElapsedTimer countTimeConsumed; QElapsedTimer countTimeConsumed;
countTimeConsumed.start(); countTimeConsumed.start();
m_isSucceed = true;
m_meshliteContext = meshlite_create_context(); m_meshliteContext = meshlite_create_context();
initMeshUtils(); initMeshUtils();

View File

@ -39,6 +39,7 @@ public:
void setGeneratedCacheContext(GeneratedCacheContext *cacheContext); void setGeneratedCacheContext(GeneratedCacheContext *cacheContext);
void setSmoothNormal(bool smoothNormal); void setSmoothNormal(bool smoothNormal);
void setWeldEnabled(bool weldEnabled); void setWeldEnabled(bool weldEnabled);
bool isSucceed();
MeshLoader *takeResultMesh(); MeshLoader *takeResultMesh();
MeshLoader *takePartPreviewMesh(const QUuid &partId); MeshLoader *takePartPreviewMesh(const QUuid &partId);
const std::set<QUuid> &requirePreviewPartIds(); const std::set<QUuid> &requirePreviewPartIds();
@ -51,6 +52,7 @@ public slots:
void process(); void process();
private: private:
Snapshot *m_snapshot; Snapshot *m_snapshot;
bool m_isSucceed;
MeshLoader *m_mesh; MeshLoader *m_mesh;
std::map<QUuid, MeshLoader *> m_partPreviewMeshMap; std::map<QUuid, MeshLoader *> m_partPreviewMeshMap;
std::set<QUuid> m_requirePreviewPartIds; std::set<QUuid> m_requirePreviewPartIds;

View File

@ -21,38 +21,47 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
retainSizePolicy.setRetainSizeWhenHidden(true); retainSizePolicy.setRetainSizeWhenHidden(true);
m_visibleButton = new QPushButton(); m_visibleButton = new QPushButton();
m_visibleButton->setToolTip(tr("Show/hide nodes"));
m_visibleButton->setSizePolicy(retainSizePolicy); m_visibleButton->setSizePolicy(retainSizePolicy);
initButton(m_visibleButton); initButton(m_visibleButton);
m_lockButton = new QPushButton(); m_lockButton = new QPushButton();
m_lockButton->setToolTip(tr("Lock/unlock nodes"));
m_lockButton->setSizePolicy(retainSizePolicy); m_lockButton->setSizePolicy(retainSizePolicy);
initButton(m_lockButton); initButton(m_lockButton);
m_subdivButton = new QPushButton(); m_subdivButton = new QPushButton();
m_subdivButton->setToolTip(tr("Square/Round"));
m_subdivButton->setSizePolicy(retainSizePolicy); m_subdivButton->setSizePolicy(retainSizePolicy);
initButton(m_subdivButton); initButton(m_subdivButton);
m_disableButton = new QPushButton(); m_disableButton = new QPushButton();
m_disableButton->setToolTip(tr("Join/Remove from final result"));
m_disableButton->setSizePolicy(retainSizePolicy); m_disableButton->setSizePolicy(retainSizePolicy);
initButton(m_disableButton); initButton(m_disableButton);
m_xMirrorButton = new QPushButton(); m_xMirrorButton = new QPushButton();
m_xMirrorButton->setToolTip(tr("Toggle mirror"));
m_xMirrorButton->setSizePolicy(retainSizePolicy); m_xMirrorButton->setSizePolicy(retainSizePolicy);
initButton(m_xMirrorButton); initButton(m_xMirrorButton);
m_deformButton = new QPushButton(); m_deformButton = new QPushButton();
m_deformButton->setToolTip(tr("Deform"));
m_deformButton->setSizePolicy(retainSizePolicy); m_deformButton->setSizePolicy(retainSizePolicy);
initButton(m_deformButton); initButton(m_deformButton);
m_roundButton = new QPushButton; m_roundButton = new QPushButton;
m_roundButton->setToolTip(tr("Toggle round end"));
m_roundButton->setSizePolicy(retainSizePolicy); m_roundButton->setSizePolicy(retainSizePolicy);
initButton(m_roundButton); initButton(m_roundButton);
m_colorButton = new QPushButton; m_colorButton = new QPushButton;
m_colorButton->setToolTip(tr("Color and material picker"));
m_colorButton->setSizePolicy(retainSizePolicy); m_colorButton->setSizePolicy(retainSizePolicy);
initButton(m_colorButton); initButton(m_colorButton);
m_wrapButton = new QPushButton; m_wrapButton = new QPushButton;
m_wrapButton->setToolTip(tr("Toggle convex wrap"));
m_wrapButton->setSizePolicy(retainSizePolicy); m_wrapButton->setSizePolicy(retainSizePolicy);
initButton(m_wrapButton); initButton(m_wrapButton);