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
parent
2bbb222e02
commit
b65205a48c
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue