From b613a4ea278516d5ce57325ac7dda5cc819c0daa Mon Sep 17 00:00:00 2001 From: Jolbas <39026960+Jolbas@users.noreply.github.com> Date: Thu, 20 Apr 2023 18:06:45 +0200 Subject: [PATCH 1/2] Refactor Navigation Cube -Use std commands in menu coming with icons -Only draggable if activated in menu -Remove textures except labels and used gl fill instead -Borders on surrounding buttons -Fix some openGL issues -Remove duplicate parameter managment. Kept and improved the one in View3DSettings -Remove lots of other redundant code -Replaced FontSize param with FontZoom and enabled auto zoom/size on labels. -Merged BorderColor and TextColor to single EmphaseColor parameter -Merged ButtonColor and FrontColor to BaseColor parameter -Added ChamferSize parameter to control edge and corner size -Use glDrawArrays() innstead of glBegin() and glEnd() -Draw butt ends on RGB coordinate system -Fixe issues where cube switch corner on resize window --- src/Gui/DlgSettingsNavigation.cpp | 36 +- src/Gui/DlgSettingsNavigation.h | 1 - src/Gui/DlgSettingsNavigation.ui | 46 +- src/Gui/NaviCube.cpp | 1777 ++++++++++------------------- src/Gui/NaviCube.h | 20 +- src/Gui/View3DInventor.cpp | 1 - src/Gui/View3DInventorViewer.cpp | 10 +- src/Gui/View3DInventorViewer.h | 3 +- src/Gui/View3DSettings.cpp | 134 ++- src/Gui/View3DSettings.h | 12 +- 10 files changed, 732 insertions(+), 1308 deletions(-) diff --git a/src/Gui/DlgSettingsNavigation.cpp b/src/Gui/DlgSettingsNavigation.cpp index 198fe0f587..895d17de7c 100644 --- a/src/Gui/DlgSettingsNavigation.cpp +++ b/src/Gui/DlgSettingsNavigation.cpp @@ -36,7 +36,7 @@ #include "DlgSettingsNavigation.h" #include "ui_DlgSettingsNavigation.h" #include "MainWindow.h" -#include "NaviCube.h" +#include "View3DSettings.h" #include "NavigationStyle.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" @@ -57,7 +57,7 @@ DlgSettingsNavigation::DlgSettingsNavigation(QWidget* parent) , q0(0), q1(0), q2(0), q3(1) { ui->setupUi(this); - ui->naviCubeButtonColor->setAllowTransparency(true); + ui->naviCubeBaseColor->setAllowTransparency(true); retranslate(); } @@ -93,8 +93,7 @@ void DlgSettingsNavigation::saveSettings() ui->naviCubeCorner->onSave(); ui->naviCubeToNearest->onSave(); ui->prefCubeSize->onSave(); - ui->naviCubeFontSize->onSave(); - ui->naviCubeButtonColor->onSave(); + ui->naviCubeBaseColor->onSave(); bool showNaviCube = ui->groupBoxNaviCube->isChecked(); hGrp->SetBool("ShowNaviCube", showNaviCube); @@ -113,21 +112,6 @@ void DlgSettingsNavigation::saveSettings() hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/NaviCube"); hGrp->SetASCII("FontString", ui->naviCubeFontName->currentText().toLatin1()); - - recreateNaviCubes(); -} - -void DlgSettingsNavigation::recreateNaviCubes() -{ - // we changed the cube's layout, therefore we must re-initialize it - // by deleting and the subsequently recreating - auto views = getMainWindow()->windows(); - for (auto view : views) { - if (auto view3d = qobject_cast(view)) { - auto viewer = view3d->getViewer(); - viewer->updateNavigationCube(); - } - } } void DlgSettingsNavigation::loadSettings() @@ -142,8 +126,7 @@ void DlgSettingsNavigation::loadSettings() ui->naviCubeCorner->onRestore(); ui->naviCubeToNearest->onRestore(); ui->prefCubeSize->onRestore(); - ui->naviCubeFontSize->onRestore(); - ui->naviCubeButtonColor->onRestore(); + ui->naviCubeBaseColor->onRestore(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/View"); @@ -190,7 +173,7 @@ void DlgSettingsNavigation::loadSettings() // fill up font styles hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/NaviCube"); - std::string defaultSansserifFont = NaviCube::getDefaultSansserifFont().toStdString(); + std::string defaultSansserifFont = NaviCubeSettings::getDefaultSansserifFont().toStdString(); // we purposely allow all available fonts on the system #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -206,15 +189,6 @@ void DlgSettingsNavigation::loadSettings() indexFamilyNames = 0; ui->naviCubeFontName->setCurrentIndex(indexFamilyNames); - // if the FontSize parameter does not yet exist, set the default value - // the default is defined in NaviCubeImplementation::getDefaultFontSize() - // but not accessible if there is no cube yet drawn - if (hGrp->GetInt("FontSize", 0) == 0) { - // the "4" is the hardcoded m_OverSample from getDefaultFontSize() - ui->naviCubeFontSize->setValue(int(0.18 * 4 * ui->prefCubeSize->value())); - // we purposely don't write to the parameters because the writing would - // also be done when the user cancels the preferences dialog - } } void DlgSettingsNavigation::onMouseButtonClicked() diff --git a/src/Gui/DlgSettingsNavigation.h b/src/Gui/DlgSettingsNavigation.h index 3a32389334..41ec66f8f3 100644 --- a/src/Gui/DlgSettingsNavigation.h +++ b/src/Gui/DlgSettingsNavigation.h @@ -53,7 +53,6 @@ public: private: void onMouseButtonClicked(); void onNewDocViewChanged(int); - void recreateNaviCubes(); protected: void changeEvent(QEvent *e) override; diff --git a/src/Gui/DlgSettingsNavigation.ui b/src/Gui/DlgSettingsNavigation.ui index cdfba602f2..90b7607bb6 100644 --- a/src/Gui/DlgSettingsNavigation.ui +++ b/src/Gui/DlgSettingsNavigation.ui @@ -194,53 +194,15 @@ - - - - Font size: - - - - - - - - 0 - 0 - - - - Font size of the navigation cube - - - 1 - - - 999 - - - 5 - - - 100 - - - FontSize - - - NaviCube - - - - + - Button color + Color - + color for all elements around the cube @@ -253,7 +215,7 @@ around the cube - ButtonColor + BaseColor NaviCube diff --git a/src/Gui/NaviCube.cpp b/src/Gui/NaviCube.cpp index 82ddae39a4..7c6172f13c 100644 --- a/src/Gui/NaviCube.cpp +++ b/src/Gui/NaviCube.cpp @@ -51,6 +51,7 @@ #include "NaviCube.h" #include "Application.h" #include "Command.h" +#include "Action.h" #include "MainWindow.h" #include "View3DInventorViewer.h" #include "View3DInventor.h" @@ -60,69 +61,33 @@ using namespace Eigen; using namespace std; using namespace Gui; -// TODO -// ortho / persp -// stay in window -// corner angle -// menu actions -// size -// XYZ position -// menu feedback -// colors -// antialise cube icon -// translation -// DONE -// - permanent menu ("NaviCube_Menu" -// - improved hit testing -// - improved graphics (text now black) -// - first stab at supporting translations -class Face { -public: - int m_FirstVertex; - int m_VertexCount; - GLuint m_TextureId; - QColor m_Color; - int m_PickId; - int m_PickTexId; - GLuint m_PickTextureId; - int m_RenderPass; - Face( - int firstVertex, - int vertexCount, - GLuint textureId, - int pickId, - int pickTexId, - GLuint pickTextureId, - const QColor& color, - int renderPass - ) - { - m_FirstVertex = firstVertex; - m_VertexCount = vertexCount; - m_TextureId = textureId; - m_PickId = pickId; - m_PickTexId = pickTexId; - m_PickTextureId = pickTextureId; - m_Color = color; - m_RenderPass = renderPass; - } + +struct Face { + int type; + vector vertexArray; +}; +struct LabelTexture { + vector vertexArray; + qreal fontSize; + QOpenGLTexture *texture = nullptr; + string label; }; -class NaviCubeImplementation : public ParameterGrp::ObserverType { - Q_DECLARE_TR_FUNCTIONS(NaviCubeImplementation) + +class NaviCubeImplementation { public: explicit NaviCubeImplementation(Gui::View3DInventorViewer*); - ~NaviCubeImplementation() override; - int getDefaultFontSize(); + ~NaviCubeImplementation(); void drawNaviCube(); void createContextMenu(const std::vector& cmd); + void createCubeFaceTextures(); - /// Observer message from the ParameterGrp - void OnChange(ParameterGrp::SubjectType& rCaller, ParameterGrp::MessageType Reason) override; - void applySettings(ParameterGrp&); + void moveToCorner(NaviCube::Corner c); + void setLabels(const std::vector& labels); bool processSoEvent(const SoEvent* ev); + void setSize(int size); private: bool mousePressed(short x, short y); @@ -131,112 +96,103 @@ private: int pickFace(short x, short y); bool inDragZone(short x, short y); + void prepare(); void handleResize(); void handleMenu(); void setHilite(int); - void initNaviCube(QtGLWidget*); - void addFace(float gap, const Vector3f&, const Vector3f&, int, int, int, bool flag = false); + void addCubeFace(const Vector3f&, const Vector3f&, int, int); - GLuint createCubeFaceTex(QtGLWidget* gl, float gap, const char* text, int shape); - GLuint createButtonTex(QtGLWidget*, int); - GLuint createMenuTex(QtGLWidget*, bool); + void addButtonFaceTex(QtGLWidget*, int); + void addButtonFace(int); SbRotation setView(float, float) const; SbRotation rotateView(SbRotation, int axis, float rotAngle, SbVec3f customAxis = SbVec3f(0, 0, 0)) const; void rotateView(const SbRotation&); QString str(const char* str); - char* enum2str(int); QMenu* createNaviCubeMenu(); public: - enum { // - TEX_FRONT = 1, // 0 is reserved for 'nothing picked' - TEX_REAR, - TEX_TOP, - TEX_BOTTOM, - TEX_LEFT, - TEX_RIGHT, - TEX_FRONT_FACE, - TEX_CORNER_FACE, - TEX_EDGE_FACE, - TEX_FRONT_TOP, - TEX_FRONT_BOTTOM, - TEX_FRONT_LEFT, - TEX_FRONT_RIGHT, - TEX_REAR_TOP, - TEX_REAR_BOTTOM, - TEX_REAR_LEFT, - TEX_REAR_RIGHT, - TEX_TOP_LEFT, - TEX_TOP_RIGHT, - TEX_BOTTOM_LEFT, - TEX_BOTTOM_RIGHT, - TEX_BOTTOM_RIGHT_REAR, - TEX_BOTTOM_FRONT_RIGHT, - TEX_BOTTOM_LEFT_FRONT, - TEX_BOTTOM_REAR_LEFT, - TEX_TOP_RIGHT_FRONT, - TEX_TOP_FRONT_LEFT, - TEX_TOP_LEFT_REAR, - TEX_TOP_REAR_RIGHT, - TEX_ARROW_NORTH, - TEX_ARROW_SOUTH, - TEX_ARROW_EAST, - TEX_ARROW_WEST, - TEX_ARROW_RIGHT, - TEX_ARROW_LEFT, - TEX_DOT_BACKSIDE, - TEX_VIEW_MENU_ICON, - TEX_VIEW_MENU_FACE + enum { + PID_NONE, + PID_FRONT, + PID_TOP, + PID_RIGHT, + PID_REAR, + PID_BOTTOM, + PID_LEFT, + PID_FRONT_TOP, + PID_FRONT_BOTTOM, + PID_FRONT_RIGHT, + PID_FRONT_LEFT, + PID_REAR_TOP, + PID_REAR_BOTTOM, + PID_REAR_RIGHT, + PID_REAR_LEFT, + PID_TOP_RIGHT, + PID_TOP_LEFT, + PID_BOTTOM_RIGHT, + PID_BOTTOM_LEFT, + PID_FRONT_TOP_RIGHT, + PID_FRONT_TOP_LEFT, + PID_FRONT_BOTTOM_RIGHT, + PID_FRONT_BOTTOM_LEFT, + PID_REAR_TOP_RIGHT, + PID_REAR_TOP_LEFT, + PID_REAR_BOTTOM_RIGHT, + PID_REAR_BOTTOM_LEFT, + PID_ARROW_NORTH, + PID_ARROW_SOUTH, + PID_ARROW_EAST, + PID_ARROW_WEST, + PID_ARROW_RIGHT, + PID_ARROW_LEFT, + PID_DOT_BACKSIDE, + PID_VIEW_MENU }; enum { DIR_UP, DIR_RIGHT, DIR_OUT }; enum { - SHAPE_SQUARE, SHAPE_EDGE, SHAPE_CORNER + SHAPE_NONE, SHAPE_MAIN, SHAPE_EDGE, SHAPE_CORNER, SHAPE_BUTTON }; Gui::View3DInventorViewer* m_View3DInventorViewer; void drawNaviCube(bool picking); - int m_OverSample = 4; - int m_CubeWidgetSize = 0; - int m_CubeWidgetPosX = 0; - int m_CubeWidgetPosY = 0; - int m_PrevWidth = 0; - int m_PrevHeight = 0; - QColor m_TextColor; + int m_CubeWidgetSize = 132; + SbVec2f m_RelPos = SbVec2f(1.0f,1.0f); + SbVec2s m_ViewSize = SbVec2s(0,0); + SbVec2s m_PosAreaBase = SbVec2s(0,0); + SbVec2s m_PosAreaSize = SbVec2s(0,0); + SbVec2s m_PosOffset = SbVec2s(0,0); + QColor m_BaseColor; + QColor m_EmphaseColor; QColor m_HiliteColor; - QColor m_ButtonColor; - QColor m_FrontColor; - QColor m_BorderColor; + bool m_ShowCS = true; int m_HiliteId = 0; bool m_MouseDown = false; bool m_Dragging = false; + bool m_Draggable = false; bool m_MightDrag = false; - double m_BorderWidth; - NaviCube::Corner m_Corner = NaviCube::TopRightCorner; + double m_BorderWidth = 1.1; bool m_RotateToNearest = true; int m_NaviStepByTurn = 8; - int m_CubeTextSize = 0; - std::string m_CubeTextFont; + float m_FontZoom = 0.3; + float m_Chamfer = 0.12; + std::string m_TextFont; + int m_FontWeight = 0; + int m_FontStretch = 0; QtGLFramebufferObject* m_PickingFramebuffer; - bool m_NaviCubeInitialised = false; + bool m_Prepared = false; - vector m_IndexArray; - vector m_TextureCoordArray; - vector m_VertexArray; - map> m_VertexArrays2; - map m_Textures; - vector m_Faces; - vector m_Buttons; - vector m_glTextures; + map m_Faces; + map m_LabelTextures; static vector m_commands; - static vector m_labels; + QMenu* m_Menu; }; @@ -261,19 +217,33 @@ bool NaviCube::processSoEvent(const SoEvent* ev) { } vector NaviCubeImplementation::m_commands; -vector NaviCubeImplementation::m_labels; void NaviCube::setCorner(Corner c) { - m_NaviCubeImplementation->m_Corner = c; - m_NaviCubeImplementation->m_PrevWidth = 0; - m_NaviCubeImplementation->m_PrevHeight = 0; + m_NaviCubeImplementation->moveToCorner(c); +} + +void NaviCube::setOffset(int x, int y) { + m_NaviCubeImplementation->m_PosOffset = SbVec2s(x, y); + m_NaviCubeImplementation->m_ViewSize = SbVec2s(0,0); +} + +bool NaviCube::isDraggable() { + return m_NaviCubeImplementation->m_Draggable; +} + +void NaviCube::setDraggable(bool draggable) { + m_NaviCubeImplementation->m_Draggable = draggable; } void NaviCube::setSize(int size) { - m_NaviCubeImplementation->m_CubeWidgetSize = size; + m_NaviCubeImplementation->setSize(size); +} +void NaviCube::setChamfer(float chamfer) +{ + m_NaviCubeImplementation->m_Chamfer = min(max(0.05f, chamfer), 0.18f); + m_NaviCubeImplementation->m_Prepared = false; } - void NaviCube::setNaviRotateToNearest(bool toNearest) { m_NaviCubeImplementation->m_RotateToNearest = toNearest; @@ -286,22 +256,37 @@ void NaviCube::setNaviStepByTurn(int steps) void NaviCube::setFont(std::string font) { - m_NaviCubeImplementation->m_CubeTextFont = font; + m_NaviCubeImplementation->m_TextFont = font; + m_NaviCubeImplementation->m_Prepared = false; } -void NaviCube::setFontSize(int size) +void NaviCube::setFontWeight(int weight) { - m_NaviCubeImplementation->m_CubeTextSize = size; + m_NaviCubeImplementation->m_FontWeight = weight; + m_NaviCubeImplementation->m_Prepared = false; } -void NaviCube::setTextColor(QColor TextColor) +void NaviCube::setFontStretch(int stretch) { - m_NaviCubeImplementation->m_TextColor = TextColor; + m_NaviCubeImplementation->m_FontStretch = stretch; + m_NaviCubeImplementation->m_Prepared = false; } -void NaviCube::setFrontColor(QColor FrontColor) +void NaviCube::setFontZoom(float zoom) { - m_NaviCubeImplementation->m_FrontColor = FrontColor; + m_NaviCubeImplementation->m_FontZoom = zoom; + m_NaviCubeImplementation->m_Prepared = false; +} + +void NaviCube::setBaseColor(QColor bColor) +{ + m_NaviCubeImplementation->m_BaseColor = bColor; +} + +void NaviCube::setEmphaseColor(QColor eColor) +{ + m_NaviCubeImplementation->m_EmphaseColor = eColor; + m_NaviCubeImplementation->m_Prepared = false; } void NaviCube::setHiliteColor(QColor HiliteColor) @@ -309,181 +294,56 @@ void NaviCube::setHiliteColor(QColor HiliteColor) m_NaviCubeImplementation->m_HiliteColor = HiliteColor; } -void NaviCube::setButtonColor(QColor ButtonColor) -{ - m_NaviCubeImplementation->m_ButtonColor = ButtonColor; -} - void NaviCube::setBorderWidth(double BorderWidth) { m_NaviCubeImplementation->m_BorderWidth = BorderWidth; } -void NaviCube::setBorderColor(QColor BorderColor) + +void NaviCube::setShowCS(bool showCS) { - m_NaviCubeImplementation->m_BorderColor = BorderColor; + m_NaviCubeImplementation->m_ShowCS = showCS; } -QString NaviCube::getDefaultSansserifFont() +void NaviCube::setNaviCubeLabels(const std::vector& labels) { - // "FreeCAD NaviCube" family susbtitutions are set in MainWindow::MainWindow - QFont font(QStringLiteral("FreeCAD NaviCube")); - font.setStyleHint(QFont::SansSerif); - // QFontInfo is required to get the actually matched font family - return QFontInfo(font).family(); + m_NaviCubeImplementation->setLabels(labels); +} +void NaviCubeImplementation::setLabels(const std::vector& labels) +{ + m_LabelTextures[PID_FRONT].label = labels[0]; + m_LabelTextures[PID_TOP].label = labels[1]; + m_LabelTextures[PID_RIGHT].label = labels[2]; + m_LabelTextures[PID_REAR].label = labels[3]; + m_LabelTextures[PID_BOTTOM].label = labels[4]; + m_LabelTextures[PID_LEFT].label = labels[5]; + m_Prepared = false; } -int NaviCube::getDefaultFontSize() + +NaviCubeImplementation::NaviCubeImplementation(Gui::View3DInventorViewer* viewer) { - return this->m_NaviCubeImplementation->getDefaultFontSize(); -} - -NaviCubeImplementation::NaviCubeImplementation( - Gui::View3DInventorViewer* viewer) { - m_View3DInventorViewer = viewer; - - auto hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/NaviCube"); - hGrp->Attach(this); - - applySettings(*hGrp); - m_PickingFramebuffer = nullptr; m_Menu = createNaviCubeMenu(); } -NaviCubeImplementation::~NaviCubeImplementation() { - auto hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/NaviCube"); - hGrp->Detach(this); - +NaviCubeImplementation::~NaviCubeImplementation() +{ delete m_Menu; if (m_PickingFramebuffer) delete m_PickingFramebuffer; - for (vector::iterator f = m_Faces.begin(); f != m_Faces.end(); f++) - delete* f; - for (vector::iterator t = m_glTextures.begin(); t != m_glTextures.end(); t++) - delete* t; -} - -int NaviCubeImplementation::getDefaultFontSize() -{ - int texSize = m_CubeWidgetSize * m_OverSample; - return int(0.18 * texSize); -} - -void NaviCubeImplementation::applySettings(ParameterGrp& rGrp) -{ - NaviCubeImplementation::OnChange(rGrp, "TextColor"); - NaviCubeImplementation::OnChange(rGrp, "FrontColor"); - NaviCubeImplementation::OnChange(rGrp, "HiliteColor"); - NaviCubeImplementation::OnChange(rGrp, "ButtonColor"); - NaviCubeImplementation::OnChange(rGrp, "CornerNaviCube"); - NaviCubeImplementation::OnChange(rGrp, "CubeSize"); - NaviCubeImplementation::OnChange(rGrp, "NaviRotateToNearest"); - NaviCubeImplementation::OnChange(rGrp, "NaviStepByTurn"); - NaviCubeImplementation::OnChange(rGrp, "BorderWidth"); - NaviCubeImplementation::OnChange(rGrp, "BorderColor"); - NaviCubeImplementation::OnChange(rGrp, "FontSize"); - NaviCubeImplementation::OnChange(rGrp, "FontString"); -} - -void NaviCubeImplementation::OnChange(ParameterGrp::SubjectType& rCaller, - ParameterGrp::MessageType reason) -{ - const auto& rGrp = static_cast(rCaller); - - if (strcmp(reason, "TextColor") == 0) { - // the colors are stored in the form RRGGBBAA as unsigned long - // QColor expects the form AARRGGBB therefore we must make a shift in writing to QColor - unsigned long col = rGrp.GetUnsigned(reason, 255); - // 255 is RRR,GGG,BBB,AAA: 0,0,0,255 - m_TextColor = App::Color::fromPackedRGBA(col); - } - else if (strcmp(reason, "FrontColor") == 0) { - unsigned long col = rGrp.GetUnsigned(reason, 3806916544); - // 3236096495 is RRR,GGG,BBB,AAA: 226,232,239,192 - m_FrontColor = App::Color::fromPackedRGBA(col); - } - else if (strcmp(reason, "HiliteColor") == 0) { - unsigned long col = rGrp.GetUnsigned(reason, 2867003391); - // 2867003391 is RRR,GGG,BBB,AAA: 170,226,255,255 - m_HiliteColor = App::Color::fromPackedRGBA(col); - } - else if (strcmp(reason, "ButtonColor") == 0) { - unsigned long col = rGrp.GetUnsigned(reason, 3806916480); - // 3806916480 is RRR,GGG,BBB,AAA: 226,232,239,128 - m_ButtonColor = App::Color::fromPackedRGBA(col); - } - else if (strcmp(reason, "CornerNaviCube") == 0) { - m_Corner = static_cast(rGrp.GetInt(reason, 1)); - } - else if (strcmp(reason, "CubeSize") == 0) { - m_CubeWidgetSize = rGrp.GetInt(reason, 132); - } - else if (strcmp(reason, "NaviRotateToNearest") == 0) { - m_RotateToNearest = rGrp.GetBool(reason, true); - } - else if (strcmp(reason, "NaviStepByTurn") == 0) { - m_NaviStepByTurn = rGrp.GetInt(reason, 8); - } - else if (strcmp(reason, "BorderWidth") == 0) { - m_BorderWidth = rGrp.GetFloat(reason, 1.1); - } - else if (strcmp(reason, "BorderColor") == 0) { - unsigned long col = rGrp.GetUnsigned(reason, 842150655); - // 842150655 is RRR,GGG,BBB,AAA: 50,50,50,255 - m_BorderColor = App::Color::fromPackedRGBA(col); - } - else if (strcmp(reason, "FontSize") == 0) { - m_CubeTextSize = rGrp.GetInt(reason, getDefaultFontSize()); - } - else if (strcmp(reason, "FontString") == 0) { - m_CubeTextFont = (rGrp.GetASCII( - reason, NaviCube::getDefaultSansserifFont().toStdString().c_str())); + for (auto tex: m_LabelTextures) { + delete tex.second.texture; } } -char* NaviCubeImplementation::enum2str(int positionEnum) { - switch (positionEnum) { - default: return "???"; - case TEX_FRONT: return "TEX_FRONT"; - case TEX_REAR: return "TEX_REAR"; - case TEX_TOP: return "TEX_TOP"; - case TEX_BOTTOM: return "TEX_BOTTOM"; - case TEX_RIGHT: return "TEX_RIGHT"; - case TEX_LEFT: return "TEX_LEFT"; - case TEX_FRONT_FACE: return "TEX_FRONT_FACE"; - case TEX_CORNER_FACE: return "TEX_CORNER_FACE"; - case TEX_EDGE_FACE: return "TEX_EDGE_FACE"; - case TEX_FRONT_TOP: return "TEX_FRONT_TOP"; - case TEX_FRONT_BOTTOM: return "TEX_FRONT_BOTTOM"; - case TEX_FRONT_LEFT: return "TEX_FRONT_LEFT"; - case TEX_FRONT_RIGHT: return "TEX_FRONT_RIGHT"; - case TEX_REAR_TOP: return "TEX_REAR_TOP"; - case TEX_REAR_BOTTOM: return "TEX_REAR_BOTTOM"; - case TEX_REAR_LEFT: return "TEX_REAR_LEFT"; - case TEX_REAR_RIGHT: return "TEX_REAR_RIGHT"; - case TEX_BOTTOM_RIGHT_REAR: return "TEX_BOTTOM_RIGHT_REAR"; - case TEX_BOTTOM_FRONT_RIGHT: return "TEX_BOTTOM_FRONT_RIGHT"; - case TEX_BOTTOM_LEFT_FRONT: return "TEX_BOTTOM_LEFT_FRONT"; - case TEX_BOTTOM_REAR_LEFT: return "TEX_BOTTOM_REAR_LEFT"; - case TEX_TOP_RIGHT_FRONT: return "TEX_TOP_RIGHT_FRONT"; - case TEX_TOP_FRONT_LEFT: return "TEX_TOP_FRONT_LEFT"; - case TEX_TOP_LEFT_REAR: return "TEX_TOP_LEFT_REAR"; - case TEX_TOP_REAR_RIGHT: return "TEX_TOP_REAR_RIGHT"; - case TEX_ARROW_NORTH: return "TEX_ARROW_NORTH"; - case TEX_ARROW_SOUTH: return "TEX_ARROW_SOUTH"; - case TEX_ARROW_EAST: return "TEX_ARROW_EAST"; - case TEX_ARROW_WEST: return "TEX_ARROW_WEST"; - case TEX_ARROW_RIGHT: return "TEX_ARROW_RIGHT"; - case TEX_ARROW_LEFT: return "TEX_ARROW_LEFT"; - case TEX_DOT_BACKSIDE: return "TEX_DOT_BACKSIDE"; - case TEX_VIEW_MENU_ICON: return "TEX_VIEW_MENU_ICON"; - case TEX_VIEW_MENU_FACE: return "TEX_VIEW_MENU"; - } -} +void NaviCubeImplementation::moveToCorner(NaviCube::Corner c) { + if (c == NaviCube::TopLeftCorner) m_RelPos = SbVec2f(0.0f, 1.0f); + else if (c == NaviCube::TopRightCorner) m_RelPos = SbVec2f(1.0f, 1.0f); + else if (c == NaviCube::BottomLeftCorner) m_RelPos = SbVec2f(0.0f, 0.0f); + else if (c == NaviCube::BottomRightCorner) m_RelPos = SbVec2f(1.0f, 0.0f); + } auto convertWeights = [](int weight) -> QFont::Weight { if (weight >= 87) @@ -505,541 +365,273 @@ auto convertWeights = [](int weight) -> QFont::Weight { return QFont::Thin; }; -GLuint NaviCubeImplementation::createCubeFaceTex(QtGLWidget* gl, float gap, const char* text, - int shape) -{ - int texSize = m_CubeWidgetSize * m_OverSample; - float gapi = texSize * gap; - QImage image(texSize, texSize, QImage::Format_ARGB32); - image.fill(qRgba(255, 255, 255, 0)); - QPainter paint; - paint.begin(&image); - paint.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - if (text) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/NaviCube"); - paint.setPen(Qt::white); - QFont sansFont; - // check the user settings - QString fontString = QString::fromStdString(m_CubeTextFont); - // Override fromString - if (hGrp->GetInt("FontWeight") > 0) { - sansFont.setWeight(convertWeights(hGrp->GetInt("FontWeight"))); - } - if (hGrp->GetInt("FontStretch") > 0) { - sansFont.setStretch(hGrp->GetInt("FontStretch")); - } - sansFont.fromString(fontString); - sansFont.setPointSize(m_CubeTextSize); - paint.setFont(sansFont); - paint.drawText( - QRect(0, 0, texSize, texSize), Qt::AlignCenter, qApp->translate("Gui::NaviCube", text)); +void NaviCubeImplementation::createCubeFaceTextures() { + int texSize = 128; // Works well for the max cube size 1024 + // find font sizes + QFont font; + QString fontString = QString::fromStdString(m_TextFont); + font.fromString(fontString); + if (m_FontWeight > 0) { + font.setWeight(convertWeights(m_FontWeight)); } - else if (shape == SHAPE_SQUARE) { - QPainterPath pathSquare; - auto rectSquare = - QRectF(gapi, gapi, (qreal)texSize - 2.0 * gapi, (qreal)texSize - 2.0 * gapi); - // Qt's coordinate system is x->left y->down, - // this must be taken into account on operations - pathSquare.moveTo(rectSquare.left() , rectSquare.bottom() - gapi); - pathSquare.lineTo(rectSquare.left() + gapi , rectSquare.bottom()); - pathSquare.lineTo(rectSquare.right() - gapi , rectSquare.bottom()); - pathSquare.lineTo(rectSquare.right() , rectSquare.bottom() - gapi); - pathSquare.lineTo(rectSquare.right() , rectSquare.top() + gapi); - pathSquare.lineTo(rectSquare.right() - gapi , rectSquare.top()); - pathSquare.lineTo(rectSquare.left() + gapi , rectSquare.top()); - pathSquare.lineTo(rectSquare.left() , rectSquare.top() + gapi); - pathSquare.closeSubpath(); - paint.fillPath(pathSquare, Qt::white); + if (m_FontStretch > 0) { + font.setStretch(m_FontStretch); } - else if (shape == SHAPE_CORNER) { - QPainterPath pathCorner; - // the hexagon edges are of length sqrt(2) * gapi - const auto hexWidth = 2 * sqrt(2) * gapi; // hexagon vertex to vertex distance - const auto hexHeight = sqrt(3) * sqrt(2) * gapi; // edge to edge distance - auto rectCorner = QRectF((texSize - hexWidth) / 2, (texSize - hexHeight) / 2, hexWidth, hexHeight); - // Qt's coordinate system is x->left y->down, this must be taken into account on operations - pathCorner.moveTo(rectCorner.left() , rectCorner.bottom() - hexHeight / 2); // left middle vertex - pathCorner.lineTo(rectCorner.left() + hexWidth * 0.25 , rectCorner.bottom()); // left lower - pathCorner.lineTo(rectCorner.left() + hexWidth * 0.75 , rectCorner.bottom()); // right lower - pathCorner.lineTo(rectCorner.right() , rectCorner.bottom() - hexHeight / 2); // right middle - pathCorner.lineTo(rectCorner.left() + hexWidth * 0.75 , rectCorner.top()); // right upper - pathCorner.lineTo(rectCorner.left() + hexWidth * 0.25 , rectCorner.top()); // left upper - pathCorner.closeSubpath(); - paint.fillPath(pathCorner, Qt::white); - } - else if (shape == SHAPE_EDGE) { - QPainterPath pathEdge; - // since the gap is 0.12, the rect must be geometriclly shifted up with a factor - pathEdge.addRect(QRectF(2 * gapi, ((qreal)texSize - sqrt(2) * gapi) * 0.5, (qreal)texSize - 4.0 * gapi, sqrt(2) * gapi)); - paint.fillPath(pathEdge, Qt::white); - } - - paint.end(); - Q_UNUSED(gl); - auto texture = new QOpenGLTexture(image.mirrored()); - m_glTextures.push_back(texture); - texture->generateMipMaps(); - texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - return texture->textureId(); -} - -GLuint NaviCubeImplementation::createButtonTex(QtGLWidget* gl, int button) { - int texSize = m_CubeWidgetSize * m_OverSample; - QImage image(texSize, texSize, QImage::Format_ARGB32); - image.fill(qRgba(255, 255, 255, 0)); - QPainter painter; - painter.begin(&image); - painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - - QTransform transform; - transform.translate(texSize / 2, texSize / 2); - transform.scale(texSize / 2, texSize / 2); - painter.setTransform(transform); - - QPainterPath path; - - float as1 = 0.18f; // arrow size - float as3 = as1 / 3; - - switch (button) { - default: - break; - case TEX_ARROW_RIGHT: - case TEX_ARROW_LEFT: { - QRectF r(-1.00, -1.00, 2.00, 2.00); - QRectF r0(r); - r.adjust(as3, as3, -as3, -as3); - QRectF r1(r); - r.adjust(as3, as3, -as3, -as3); - QRectF r2(r); - r.adjust(as3, as3, -as3, -as3); - QRectF r3(r); - r.adjust(as3, as3, -as3, -as3); - QRectF r4(r); - - float a0 = 72; - float a1 = 45; - float a2 = 32; - - if (TEX_ARROW_LEFT == button) { - a0 = 180 - a0; - a1 = 180 - a1; - a2 = 180 - a2; - } - - path.arcMoveTo(r0, a1); - QPointF p0 = path.currentPosition(); - - path.arcMoveTo(r2, a2); - QPointF p1 = path.currentPosition(); - - path.arcMoveTo(r4, a1); - QPointF p2 = path.currentPosition(); - - path.arcMoveTo(r1, a0); - path.arcTo(r1, a0, -(a0 - a1)); - path.lineTo(p0); - path.lineTo(p1); - path.lineTo(p2); - path.arcTo(r3, a1, +(a0 - a1)); - break; - } - case TEX_ARROW_EAST: { - path.moveTo(1, 0); - path.lineTo(1 - as1, +as1); - path.lineTo(1 - as1, -as1); - break; - } - case TEX_ARROW_WEST: { - path.moveTo(-1, 0); - path.lineTo(-1 + as1, -as1); - path.lineTo(-1 + as1, +as1); - break; - } - case TEX_ARROW_SOUTH: { - path.moveTo(0, 1); - path.lineTo(-as1, 1 - as1); - path.lineTo(+as1, 1 - as1); - break; - } - case TEX_ARROW_NORTH: { - path.moveTo(0, -1); - path.lineTo(+as1, -1 + as1); - path.lineTo(-as1, -1 + as1); - break; - } - case TEX_DOT_BACKSIDE: { - path.arcTo(QRectF(1 - as1, -1, as1, as1), 0, 360); - break; - } - } - - painter.fillPath(path, Qt::white); - - painter.end(); - //image.save(str(enum2str(button))+str(".png")); - - Q_UNUSED(gl); - auto texture = new QOpenGLTexture(image.mirrored()); - m_glTextures.push_back(texture); - texture->generateMipMaps(); - texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - return texture->textureId(); -} - -GLuint NaviCubeImplementation::createMenuTex(QtGLWidget* gl, bool forPicking) { - int texSize = m_CubeWidgetSize * m_OverSample; - QImage image(texSize, texSize, QImage::Format_ARGB32); - image.fill(qRgba(0, 0, 0, 0)); - QPainter painter; - painter.begin(&image); - painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - - QTransform transform; - transform.translate(texSize * 12 / 16, texSize * 13 / 16); - transform.scale(texSize / 200.0, texSize / 200.0); // 200 == size at which this was designed - painter.setTransform(transform); - - QPainterPath path; - - if (forPicking) { - path.addRoundedRect(-25, -8, 75, 45, 6, 6); - painter.fillPath(path, Qt::white); + font.setPointSizeF(texSize); + QFontMetrics fm(font); + qreal minFontSize = texSize; + qreal maxFontSize = 0.; + vector mains = {PID_FRONT, PID_TOP, PID_RIGHT, PID_REAR, PID_BOTTOM, PID_LEFT}; + for (int pickId : mains) { + auto t = QString::fromUtf8(m_LabelTextures[pickId].label.c_str()); + float textlen = fm.horizontalAdvance(t); + m_LabelTextures[pickId].fontSize = texSize * texSize / textlen; + minFontSize = std::min(minFontSize, m_LabelTextures[pickId].fontSize); + maxFontSize = std::max(maxFontSize, m_LabelTextures[pickId].fontSize); } + if (m_FontZoom > 0.0) + maxFontSize = minFontSize + (maxFontSize - minFontSize) * m_FontZoom; else { - // top - path.moveTo(0, 0); - path.lineTo(15, 5); - path.lineTo(0, 10); - path.lineTo(-15, 5); - - painter.fillPath(path, QColor(240, 240, 240)); - - // left - QPainterPath path2; - path2.lineTo(0, 10); - path2.lineTo(-15, 5); - path2.lineTo(-15, 25); - path2.lineTo(0, 30); - painter.fillPath(path2, QColor(190, 190, 190)); - - // right - QPainterPath path3; - path3.lineTo(0, 10); - path3.lineTo(15, 5); - path3.lineTo(15, 25); - path3.lineTo(0, 30); - painter.fillPath(path3, QColor(220, 220, 220)); - - // outline - QPainterPath path4; - path4.moveTo(0, 0); - path4.lineTo(15, 5); - path4.lineTo(15, 25); - path4.lineTo(0, 30); - path4.lineTo(-15, 25); - path4.lineTo(-15, 5); - path4.lineTo(0, 0); - painter.strokePath(path4, QColor(128, 128, 128)); - - // menu triangle - QPainterPath path5; - path5.moveTo(20, 10); - path5.lineTo(40, 10); - path5.lineTo(30, 20); - path5.lineTo(20, 10); - painter.fillPath(path5, QColor(64, 64, 64)); + maxFontSize = minFontSize * std::pow(2.0, m_FontZoom); + } + for (int pickId : mains) { + m_LabelTextures[pickId].fontSize = std::min(m_LabelTextures[pickId].fontSize, maxFontSize); + QImage image(texSize, texSize, QImage::Format_ARGB32); + image.fill(qRgba(255, 255, 255, 0)); + QPainter paint; + paint.begin(&image); + paint.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + paint.setPen(Qt::white); + if (m_LabelTextures[pickId].fontSize > 0.5) { + QString text = QString::fromUtf8(m_LabelTextures[pickId].label.c_str()); + // 5% margin looks nice and prevents some artifacts + font.setPointSizeF(m_LabelTextures[pickId].fontSize * 0.9); + paint.setFont(font); + paint.drawText(QRect(0, 0, texSize, texSize), Qt::AlignCenter, text); + } + paint.end(); + if (m_LabelTextures[pickId].texture) { + delete m_LabelTextures[pickId].texture; + } + m_LabelTextures[pickId].texture = new QOpenGLTexture(image.mirrored()); + m_LabelTextures[pickId].texture->generateMipMaps(); + m_LabelTextures[pickId].texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); + m_LabelTextures[pickId].texture->setMagnificationFilter(QOpenGLTexture::Linear); } - painter.end(); - Q_UNUSED(gl); - auto texture = new QOpenGLTexture(image.mirrored()); - m_glTextures.push_back(texture); - texture->generateMipMaps(); - texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - return texture->textureId(); } -void NaviCubeImplementation::addFace(float gap, const Vector3f& x, const Vector3f& z, int frontTex, int pickTex, int pickId, bool text) { +void NaviCubeImplementation::addButtonFace(int pickId) +{ + if (m_Faces[pickId].vertexArray.size()) + m_Faces[pickId].vertexArray.clear(); + float scale = 0.005; + float offx = 0.5; + float offy = 0.5; + vector pointData; + + switch (pickId) { + default: + break; + case PID_ARROW_RIGHT: + case PID_ARROW_LEFT: { + pointData = { + 66.6, -66.6,//outer curve + 58.3, -74.0, + 49.2 ,-80.3, + 39.4 ,-85.5, + 29. , -89.5, + 25.3, -78.1,//inner curve + 34.3, -74.3, + 42.8, -69.9, + 50.8, -64.4, + 58.1, -58.1, + 53.8, -53.8,//arrowhead + 74.7, -46.8, + 70.7, -70.4 + }; + break; + } + case PID_ARROW_WEST: + case PID_ARROW_NORTH: + case PID_ARROW_SOUTH: + case PID_ARROW_EAST: { + pointData = { + 100., 0., + 80.,-18., + 80., 18. + }; + break; + } + case PID_VIEW_MENU: { + offx = 0.84; + offy = 0.84; + pointData = { + 0., 0.,//top rhombus + 15., -6., + 0., -12., + -15., -6., + 0., 0.,//left rhombus + -15., -6., + -15., 12., + 0., 18., + 0., 0.,//right rhombus + 0., 18., + 15., 12., + 15., -6. + }; + break; + } + case PID_DOT_BACKSIDE: { + int steps = 16; + for (int i = 0; i < steps; i++) { + float angle = 2.0f * M_PI * ((float)i+0.5) / (float)steps; + pointData.emplace_back(10. * cos(angle) + 87.); + pointData.emplace_back(10. * sin(angle) - 87.); + } + break; + } + } + + int count = static_cast(pointData.size())/2; + m_Faces[pickId].vertexArray.reserve(count); + for (int i = 0; i < count; i++) { + float x = pointData[i*2] * scale + offx; + float y = pointData[i*2+1] * scale + offy; + if (pickId == PID_ARROW_NORTH || pickId == PID_ARROW_WEST || pickId == PID_ARROW_LEFT) + x = 1.0 - x; + if (pickId == PID_ARROW_SOUTH || pickId == PID_ARROW_NORTH) + m_Faces[pickId].vertexArray.emplace_back(Vector3f(y, x, 0.0)); + else + m_Faces[pickId].vertexArray.emplace_back(Vector3f(x, y, 0.0)); + } + m_Faces[pickId].type = SHAPE_BUTTON; +} + + +void NaviCubeImplementation::addCubeFace( const Vector3f& x, const Vector3f& z, int shapeType, int pickId) { + m_Faces[pickId].vertexArray.clear(); + m_Faces[pickId].type = shapeType; + Vector3f y = x.cross(-z); - y = y / y.norm() * x.norm(); - int t = m_VertexArray.size(); - - m_VertexArray.emplace_back(z - x - y); - m_TextureCoordArray.emplace_back(0, 0); - m_VertexArray.emplace_back(z + x - y); - m_TextureCoordArray.emplace_back(1, 0); - m_VertexArray.emplace_back(z + x + y); - m_TextureCoordArray.emplace_back(1, 1); - m_VertexArray.emplace_back(z - x + y); - m_TextureCoordArray.emplace_back(0, 1); - - if (pickTex == TEX_FRONT_FACE) { - auto x2 = x * (1 - gap * 2); - auto y2 = y * (1 - gap * 2); - auto x4 = x * (1 - gap * 4); - auto y4 = y * (1 - gap * 4); - m_VertexArrays2[pickId].reserve(8); - m_VertexArrays2[pickId].emplace_back(z - x2 - y4); - m_VertexArrays2[pickId].emplace_back(z - x4 - y2); - m_VertexArrays2[pickId].emplace_back(z + x4 - y2); - m_VertexArrays2[pickId].emplace_back(z + x2 - y4); - - m_VertexArrays2[pickId].emplace_back(z + x2 + y4); - m_VertexArrays2[pickId].emplace_back(z + x4 + y2); - m_VertexArrays2[pickId].emplace_back(z - x4 + y2); - m_VertexArrays2[pickId].emplace_back(z - x2 + y4); + if (shapeType == SHAPE_CORNER) { + auto xC = x * m_Chamfer; + auto yC = y * m_Chamfer; + auto zC = (1 - 2 * m_Chamfer) * z; + m_Faces[pickId].vertexArray.reserve(6); + m_Faces[pickId].vertexArray.emplace_back(zC - 2 * xC); + m_Faces[pickId].vertexArray.emplace_back(zC - xC - yC); + m_Faces[pickId].vertexArray.emplace_back(zC + xC - yC); + m_Faces[pickId].vertexArray.emplace_back(zC + 2 * xC); + m_Faces[pickId].vertexArray.emplace_back(zC + xC + yC); + m_Faces[pickId].vertexArray.emplace_back(zC - xC + yC); } - else if (pickTex == TEX_EDGE_FACE) { - auto x4 = x * (1 - gap * 4); - auto y_sqrt2 = y * sqrt(2) * gap; - m_VertexArrays2[pickId].reserve(4); - m_VertexArrays2[pickId].emplace_back(z - x4 - y_sqrt2); - m_VertexArrays2[pickId].emplace_back(z + x4 - y_sqrt2); - m_VertexArrays2[pickId].emplace_back(z + x4 + y_sqrt2); - m_VertexArrays2[pickId].emplace_back(z - x4 + y_sqrt2); - } - else if (pickTex == TEX_CORNER_FACE) { - auto x_sqrt2 = x * sqrt(2) * gap; - auto y_sqrt6 = y * sqrt(6) * gap; - m_VertexArrays2[pickId].reserve(6); - m_VertexArrays2[pickId].emplace_back(z - 2 * x_sqrt2); - m_VertexArrays2[pickId].emplace_back(z - x_sqrt2 - y_sqrt6); - m_VertexArrays2[pickId].emplace_back(z + x_sqrt2 - y_sqrt6); - m_VertexArrays2[pickId].emplace_back(z + 2 * x_sqrt2); - m_VertexArrays2[pickId].emplace_back(z + x_sqrt2 + y_sqrt6); - m_VertexArrays2[pickId].emplace_back(z - x_sqrt2 + y_sqrt6); + else if (shapeType == SHAPE_EDGE) { + auto x4 = x * (1 - m_Chamfer * 4); + auto yE = y * m_Chamfer; + auto zE = z * (1 - m_Chamfer); + m_Faces[pickId].vertexArray.reserve(4); + m_Faces[pickId].vertexArray.emplace_back(zE - x4 - yE); + m_Faces[pickId].vertexArray.emplace_back(zE + x4 - yE); + m_Faces[pickId].vertexArray.emplace_back(zE + x4 + yE); + m_Faces[pickId].vertexArray.emplace_back(zE - x4 + yE); } + else if (shapeType == SHAPE_MAIN) { + auto x2 = x * (1 - m_Chamfer * 2); + auto y2 = y * (1 - m_Chamfer * 2); + auto x4 = x * (1 - m_Chamfer * 4); + auto y4 = y * (1 - m_Chamfer * 4); + m_Faces[pickId].vertexArray.reserve(8); + m_Faces[pickId].vertexArray.emplace_back(z - x2 - y4); + m_Faces[pickId].vertexArray.emplace_back(z - x4 - y2); + m_Faces[pickId].vertexArray.emplace_back(z + x4 - y2); + m_Faces[pickId].vertexArray.emplace_back(z + x2 - y4); - // TEX_TOP, TEX_FRONT_FACE, TEX_TOP - // TEX_TOP frontTex, - // TEX_FRONT_FACE pickTex, - // TEX_TOP pickId - Face* FaceFront = new Face( - m_IndexArray.size(), - 4, - m_Textures[pickTex], - pickId, - pickTex, - m_Textures[pickTex], - m_FrontColor, - 1); - m_Faces.push_back(FaceFront); + m_Faces[pickId].vertexArray.emplace_back(z + x2 + y4); + m_Faces[pickId].vertexArray.emplace_back(z + x4 + y2); + m_Faces[pickId].vertexArray.emplace_back(z - x4 + y2); + m_Faces[pickId].vertexArray.emplace_back(z - x2 + y4); - if (text) { - Face* FaceText = new Face( - m_IndexArray.size(), - 4, - m_Textures[frontTex], - pickId, - pickTex, - m_Textures[pickTex], - m_TextColor, - 2); - m_Faces.push_back(FaceText); + m_LabelTextures[pickId].vertexArray.clear(); + m_LabelTextures[pickId].vertexArray.emplace_back(z - x2 - y2); + m_LabelTextures[pickId].vertexArray.emplace_back(z + x2 - y2); + m_LabelTextures[pickId].vertexArray.emplace_back(z + x2 + y2); + m_LabelTextures[pickId].vertexArray.emplace_back(z - x2 + y2); } - - for (int i = 0; i < 4; i++) - m_IndexArray.push_back(t + i); } -void NaviCubeImplementation::initNaviCube(QtGLWidget* gl) { +void NaviCubeImplementation::setSize(int size) +{ + m_CubeWidgetSize = size; + m_ViewSize = SbVec2s(0,0); + m_Prepared = false; +} + +void NaviCubeImplementation::prepare() { + createCubeFaceTextures(); + Vector3f x(1, 0, 0); Vector3f y(0, 1, 0); Vector3f z(0, 0, 1); - float cs, sn; - cs = cos(90 * M_PI / 180); - sn = sin(90 * M_PI / 180); - Matrix3f r90x; - r90x << 1, 0, 0, - 0, cs, -sn, - 0, sn, cs; - - Matrix3f r90y; - r90y << cs, 0, sn, - 0, 1, 0, - -sn, 0, cs; - - Matrix3f r90z; - r90z << cs, sn, 0, - -sn, cs, 0, - 0, 0, 1; - - cs = cos(45 * M_PI / 180); - sn = sin(45 * M_PI / 180); - Matrix3f r45x; - r45x << 1, 0, 0, - 0, cs, -sn, - 0, sn, cs; - - Matrix3f r45z; - r45z << cs, sn, 0, - -sn, cs, 0, - 0, 0, 1; - - // first create front and backside of faces - float gap = 0.12f; - m_Textures[TEX_FRONT_FACE] = createCubeFaceTex(gl, gap, nullptr, SHAPE_SQUARE); - - vector labels = NaviCubeImplementation::m_labels; - - if (labels.size() != 6) { - labels.clear(); - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/NaviCube"); - // see https://wiki.qt.io/Technical_FAQ#How_can_I_convert_a_QString_to_char.2A_and_vice_versa.3F - QByteArray frontByteArray = tr("FRONT").toUtf8(); - labels.push_back(hGrp->GetASCII("TextFront", frontByteArray.constData())); - QByteArray rearByteArray = tr("REAR").toUtf8(); - labels.push_back(hGrp->GetASCII("TextRear", rearByteArray.constData())); - QByteArray topByteArray = tr("TOP").toUtf8(); - labels.push_back(hGrp->GetASCII("TextTop", topByteArray.constData())); - QByteArray bottomByteArray = tr("BOTTOM").toUtf8(); - labels.push_back(hGrp->GetASCII("TextBottom", bottomByteArray.constData())); - QByteArray rightByteArray = tr("RIGHT").toUtf8(); - labels.push_back(hGrp->GetASCII("TextRight", rightByteArray.constData())); - QByteArray leftByteArray = tr("LEFT").toUtf8(); - labels.push_back(hGrp->GetASCII("TextLeft", leftByteArray.constData())); - } // create the main faces - m_Textures[TEX_FRONT] = createCubeFaceTex(gl, gap, labels[0].c_str(), SHAPE_SQUARE); - m_Textures[TEX_REAR] = createCubeFaceTex(gl, gap, labels[1].c_str(), SHAPE_SQUARE); - m_Textures[TEX_TOP] = createCubeFaceTex(gl, gap, labels[2].c_str(), SHAPE_SQUARE); - m_Textures[TEX_BOTTOM] = createCubeFaceTex(gl, gap, labels[3].c_str(), SHAPE_SQUARE); - m_Textures[TEX_RIGHT] = createCubeFaceTex(gl, gap, labels[4].c_str(), SHAPE_SQUARE); - m_Textures[TEX_LEFT] = createCubeFaceTex(gl, gap, labels[5].c_str(), SHAPE_SQUARE); - - // create the arrows - m_Textures[TEX_ARROW_NORTH] = createButtonTex(gl, TEX_ARROW_NORTH); - m_Textures[TEX_ARROW_SOUTH] = createButtonTex(gl, TEX_ARROW_SOUTH); - m_Textures[TEX_ARROW_EAST] = createButtonTex(gl, TEX_ARROW_EAST); - m_Textures[TEX_ARROW_WEST] = createButtonTex(gl, TEX_ARROW_WEST); - m_Textures[TEX_ARROW_LEFT] = createButtonTex(gl, TEX_ARROW_LEFT); - m_Textures[TEX_ARROW_RIGHT] = createButtonTex(gl, TEX_ARROW_RIGHT); - m_Textures[TEX_DOT_BACKSIDE] = createButtonTex(gl, TEX_DOT_BACKSIDE); - m_Textures[TEX_VIEW_MENU_ICON] = createMenuTex(gl, false); - m_Textures[TEX_VIEW_MENU_FACE] = createMenuTex(gl, true); - - // front,back,pick,pickid - addFace(gap, x, z, TEX_TOP, TEX_FRONT_FACE, TEX_TOP, true); - x = r90x * x; - z = r90x * z; - addFace(gap, x, z, TEX_FRONT, TEX_FRONT_FACE, TEX_FRONT, true); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_LEFT, TEX_FRONT_FACE, TEX_LEFT, true); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_REAR, TEX_FRONT_FACE, TEX_REAR, true); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_RIGHT, TEX_FRONT_FACE, TEX_RIGHT, true); - x = r90x * r90z * x; - z = r90x * r90z * z; - addFace(gap, x, z, TEX_BOTTOM, TEX_FRONT_FACE, TEX_BOTTOM, true); - - // add corner faces - m_Textures[TEX_CORNER_FACE] = createCubeFaceTex(gl, gap, nullptr, SHAPE_CORNER); - // we need to rotate to the edge, thus matrix for rotation angle of 54.7 deg - cs = cos(atan(sqrt(2.0))); - sn = sin(atan(sqrt(2.0))); - Matrix3f r54x; - r54x << 1, 0, 0, - 0, cs, -sn, - 0, sn, cs; - - z = r45z * r54x * z; - x = r45z * r54x * x; - z *= sqrt(3) * (1 - 2 * gap); // corner face position along the cube diagonal - - - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_BOTTOM_RIGHT_REAR); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_BOTTOM_FRONT_RIGHT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_BOTTOM_LEFT_FRONT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_BOTTOM_REAR_LEFT); - x = r90x * r90x * r90z * x; - z = r90x * r90x * r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_TOP_RIGHT_FRONT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_TOP_FRONT_LEFT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_TOP_LEFT_REAR); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_CORNER_FACE, TEX_CORNER_FACE, TEX_TOP_REAR_RIGHT); + addCubeFace( x, z, SHAPE_MAIN, PID_TOP); + addCubeFace( x,-y, SHAPE_MAIN, PID_FRONT); + addCubeFace(-y,-x, SHAPE_MAIN, PID_LEFT); + addCubeFace(-x, y, SHAPE_MAIN, PID_REAR); + addCubeFace( y, x, SHAPE_MAIN, PID_RIGHT); + addCubeFace( x,-z, SHAPE_MAIN, PID_BOTTOM); // add edge faces - m_Textures[TEX_EDGE_FACE] = createCubeFaceTex(gl, gap, nullptr, SHAPE_EDGE); - // first back to top side - x[0] = 1; x[1] = 0; x[2] = 0; - z[0] = 0; z[1] = 0; z[2] = 1; - // rotate 45 degrees up - z = r45x * z; - x = r45x * x; - z *= sqrt(2) * (1 - gap); - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_FRONT_TOP); - x = r90x * x; - z = r90x * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_FRONT_BOTTOM); - x = r90x * x; - z = r90x * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_REAR_BOTTOM); - x = r90x * x; - z = r90x * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_REAR_TOP); - x = r90y * x; - z = r90y * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_REAR_RIGHT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_FRONT_RIGHT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_FRONT_LEFT); - x = r90z * x; - z = r90z * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_REAR_LEFT); - x = r90x * x; - z = r90x * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_TOP_LEFT); - x = r90y * x; - z = r90y * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_TOP_RIGHT); - x = r90y * x; - z = r90y * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_BOTTOM_RIGHT); - x = r90y * x; - z = r90y * z; - addFace(gap, x, z, TEX_EDGE_FACE, TEX_EDGE_FACE, TEX_BOTTOM_LEFT); + addCubeFace(x+y, x-y+z, SHAPE_CORNER, PID_FRONT_TOP_RIGHT); + addCubeFace(x-y,-x-y+z, SHAPE_CORNER, PID_FRONT_TOP_LEFT); + addCubeFace(x+y, x-y-z, SHAPE_CORNER, PID_FRONT_BOTTOM_RIGHT); + addCubeFace(x-y,-x-y-z, SHAPE_CORNER, PID_FRONT_BOTTOM_LEFT); + addCubeFace(x-y, x+y+z, SHAPE_CORNER, PID_REAR_TOP_RIGHT); + addCubeFace(x+y,-x+y+z, SHAPE_CORNER, PID_REAR_TOP_LEFT); + addCubeFace(x-y, x+y-z, SHAPE_CORNER, PID_REAR_BOTTOM_RIGHT); + addCubeFace(x+y,-x+y-z, SHAPE_CORNER, PID_REAR_BOTTOM_LEFT); - m_Buttons.push_back(TEX_ARROW_NORTH); - m_Buttons.push_back(TEX_ARROW_SOUTH); - m_Buttons.push_back(TEX_ARROW_EAST); - m_Buttons.push_back(TEX_ARROW_WEST); - m_Buttons.push_back(TEX_ARROW_LEFT); - m_Buttons.push_back(TEX_ARROW_RIGHT); - m_Buttons.push_back(TEX_DOT_BACKSIDE); + // add corner faces + addCubeFace(x, z-y, SHAPE_EDGE, PID_FRONT_TOP); + addCubeFace(x,-z-y, SHAPE_EDGE, PID_FRONT_BOTTOM); + addCubeFace(x, y-z, SHAPE_EDGE, PID_REAR_BOTTOM); + addCubeFace(x, y+z, SHAPE_EDGE, PID_REAR_TOP); + addCubeFace(z, x+y, SHAPE_EDGE, PID_REAR_RIGHT); + addCubeFace(z, x-y, SHAPE_EDGE, PID_FRONT_RIGHT); + addCubeFace(z,-x-y, SHAPE_EDGE, PID_FRONT_LEFT); + addCubeFace(z, y-x, SHAPE_EDGE, PID_REAR_LEFT); + addCubeFace(y, z-x, SHAPE_EDGE, PID_TOP_LEFT); + addCubeFace(y, x+z, SHAPE_EDGE, PID_TOP_RIGHT); + addCubeFace(y, x-z, SHAPE_EDGE, PID_BOTTOM_RIGHT); + addCubeFace(y,-z-x, SHAPE_EDGE, PID_BOTTOM_LEFT); - m_PickingFramebuffer = new QtGLFramebufferObject(2 * m_CubeWidgetSize, 2 * m_CubeWidgetSize, QtGLFramebufferObject::CombinedDepthStencil); + // create the flat buttons + addButtonFace(PID_ARROW_NORTH); + addButtonFace(PID_ARROW_SOUTH); + addButtonFace(PID_ARROW_EAST); + addButtonFace(PID_ARROW_WEST); + addButtonFace(PID_ARROW_LEFT); + addButtonFace(PID_ARROW_RIGHT); + addButtonFace(PID_DOT_BACKSIDE); + addButtonFace(PID_VIEW_MENU); + + + if (m_PickingFramebuffer) + delete m_PickingFramebuffer; + m_PickingFramebuffer = + new QtGLFramebufferObject(2 * m_CubeWidgetSize, 2 * m_CubeWidgetSize, + QtGLFramebufferObject::CombinedDepthStencil); + m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); } void NaviCubeImplementation::drawNaviCube() { - glViewport(m_CubeWidgetPosX - m_CubeWidgetSize / 2, m_CubeWidgetPosY - m_CubeWidgetSize / 2, m_CubeWidgetSize, m_CubeWidgetSize); + handleResize(); + int posX = (int)(m_RelPos[0] * m_PosAreaSize[0]) + m_PosAreaBase[0] - m_CubeWidgetSize / 2; + int posY = (int)(m_RelPos[1] * m_PosAreaSize[1]) + m_PosAreaBase[1] - m_CubeWidgetSize / 2; + glViewport(posX, posY, m_CubeWidgetSize, m_CubeWidgetSize); drawNaviCube(false); } @@ -1055,64 +647,31 @@ void NaviCubeImplementation::createContextMenu(const std::vector& c } void NaviCubeImplementation::handleResize() { - SbVec2s view = m_View3DInventorViewer->getSoRenderManager()->getSize(); - if ((m_PrevWidth != view[0]) || (m_PrevHeight != view[1])) { - if ((m_PrevWidth > 0) && (m_PrevHeight > 0)) { - // maintain position relative to closest edge - if (m_CubeWidgetPosX > m_PrevWidth / 2) - m_CubeWidgetPosX = view[0] - (m_PrevWidth - m_CubeWidgetPosX); - if (m_CubeWidgetPosY > m_PrevHeight / 2) - m_CubeWidgetPosY = view[1] - (m_PrevHeight - m_CubeWidgetPosY); - } - else { // initial position - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/NaviCube"); - int m_CubeWidgetOffsetX = hGrp->GetInt("OffsetX", 0); - int m_CubeWidgetOffsetY = hGrp->GetInt("OffsetY", 0); - switch (m_Corner) { - case NaviCube::TopLeftCorner: - m_CubeWidgetPosX = m_CubeWidgetSize * 1.1 / 2 + m_CubeWidgetOffsetX; - m_CubeWidgetPosY = view[1] - m_CubeWidgetSize * 1.1 / 2 - m_CubeWidgetOffsetY; - break; - case NaviCube::TopRightCorner: - m_CubeWidgetPosX = view[0] - m_CubeWidgetSize * 1.1 / 2 - m_CubeWidgetOffsetX; - m_CubeWidgetPosY = view[1] - m_CubeWidgetSize * 1.1 / 2 - m_CubeWidgetOffsetY; - break; - case NaviCube::BottomLeftCorner: - m_CubeWidgetPosX = m_CubeWidgetSize * 1.1 / 2 + m_CubeWidgetOffsetX; - m_CubeWidgetPosY = m_CubeWidgetSize * 1.1 / 2 + m_CubeWidgetOffsetY; - break; - case NaviCube::BottomRightCorner: - m_CubeWidgetPosX = view[0] - m_CubeWidgetSize * 1.1 / 2 - m_CubeWidgetOffsetX; - m_CubeWidgetPosY = m_CubeWidgetSize * 1.1 / 2 + m_CubeWidgetOffsetY; - break; - } - } - m_PrevWidth = view[0]; - m_PrevHeight = view[1]; - m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); + SbVec2s viewSize = m_View3DInventorViewer->getSoRenderManager()->getSize(); + if (viewSize != m_ViewSize) { + m_PosAreaBase[0] = std::min((int)(m_PosOffset[0] + m_CubeWidgetSize * 0.55), viewSize[0] / 2); + m_PosAreaBase[1] = std::min((int)(m_PosOffset[1] + m_CubeWidgetSize * 0.55), viewSize[1] / 2); + m_PosAreaSize[0] = viewSize[0] - 2 * m_PosAreaBase[0]; + m_PosAreaSize[1] = viewSize[1] - 2 * m_PosAreaBase[1]; + m_ViewSize = viewSize; } } -void NaviCubeImplementation::drawNaviCube(bool pickMode) { - // initializes stuff here when we actually have a context - // FIXME actually now that we have Qt5, we could probably do this earlier - // (as we do not need the opengl context) - if (!m_NaviCubeInitialised) { - auto gl = static_cast(m_View3DInventorViewer->viewport()); - if (!gl) +void NaviCubeImplementation::drawNaviCube(bool pickMode) +{ + if (!m_Prepared) { + if (!m_View3DInventorViewer->viewport()) return; - initNaviCube(gl); - m_NaviCubeInitialised = true; + prepare(); + m_Prepared = true; + m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); + return; } SoCamera* cam = m_View3DInventorViewer->getSoRenderManager()->getCamera(); - if (!cam) return; - handleResize(); - // Store GL state. glPushAttrib(GL_ALL_ATTRIB_BITS); GLfloat depthrange[2]; @@ -1121,24 +680,16 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) { glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); glDepthMask(GL_TRUE); - glDepthRange(0.0, 1.0); + glDepthRange(0.1f, 0.9f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - glLineWidth(2.0); glDisable(GL_LIGHTING); - //glDisable(GL_BLEND); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glDepthMask(GL_TRUE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glShadeModel(GL_SMOOTH); @@ -1147,40 +698,41 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) { glCullFace(GL_BACK); glFrontFace(GL_CCW); - glAlphaFunc(GL_GREATER, 0.25); - glEnable(GL_ALPHA_TEST); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); const float NEARVAL = 0.1f; - const float FARVAL = 10.0f; - const float dim = NEARVAL * float(tan(M_PI / 8.0)) * 1.2; - glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL); - - SbMatrix mx; - mx = cam->orientation.getValue(); - - mx = mx.inverse(); - mx[3][2] = -5.0; + const float FARVAL = 10.1f; + if (cam->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())) { + glOrtho(-2.1, 2.1, -2.1, 2.1, NEARVAL, FARVAL); + } + else { + const float dim = NEARVAL * float(tan(M_PI / 8.0)) * 1.1; + glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL); + } glMatrixMode(GL_MODELVIEW); glPushMatrix(); + + SbMatrix mx; + mx = cam->orientation.getValue(); + mx = mx.inverse(); + mx[3][2] = -5.1; + glLoadMatrixf((float*)mx); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); if (pickMode) { glDisable(GL_BLEND); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_POLYGON_SMOOTH); } else { + glEnable(GL_BLEND); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } @@ -1188,188 +740,133 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) { glClear(GL_DEPTH_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, (void*)m_VertexArray.data()); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, m_TextureCoordArray.data()); + QColor& cb = m_EmphaseColor; + // Draw coordinate system + if (!pickMode && m_ShowCS) { + glLineWidth(m_BorderWidth*2.f); + glPointSize(m_BorderWidth*2.f); + float a = -1.1f; + float b = -1.0f; + float c = 0.5f; + + float pointData[] = { + b, a, a, // X1 + c, a, a, // X2 + a, b, a, // Y1 + a, c, a, // Y2 + a, a, b, // Z1 + a, a, c, // Z2 + a, a, a //0 + }; + glVertexPointer(3, GL_FLOAT, 0, pointData); + glColor3f(1, 0, 0); + glDrawArrays(GL_LINES, 0, 2); + glDrawArrays(GL_POINTS, 0, 2); + glColor3f(0, 1, 0); + glDrawArrays(GL_LINES, 2, 2); + glDrawArrays(GL_POINTS, 2, 2); + glColor3f(0, 0, 1); + glDrawArrays(GL_LINES, 4, 2); + glDrawArrays(GL_POINTS, 4, 2); + } + + // cube faces + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + for (const auto& pair : m_Faces) { + auto f = pair.second; + if (f.type == SHAPE_BUTTON) + continue; + auto pickId = pair.first; + if (pickMode) { + glColor3ub(pickId, 0, 0); + } + else { + QColor& c = m_HiliteId == pickId ? m_HiliteColor : m_BaseColor; + glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + } + glVertexPointer(3, GL_FLOAT, 0, f.vertexArray.data()); + glDrawArrays(GL_TRIANGLE_FAN, 0, f.vertexArray.size()); + } if (!pickMode) { - // Draw the axes - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/NaviCube"); - bool ShowCS = hGrp->GetBool("ShowCS", 1); - if (ShowCS) { - glDisable(GL_TEXTURE_2D); - float a = 1.1f; - - glColor3f(1, 0, 0); - glBegin(GL_LINES); - glVertex3f(-1.1f, -1.1f, -1.1f); - glVertex3f(+0.5f, -1.1f, -1.1f); - glEnd(); - glRasterPos3d(a, -a, -a); - - glColor3f(0, 1, 0); - glBegin(GL_LINES); - glVertex3f(-1.1f, -1.1f, -1.1f); - glVertex3f(-1.1f, +0.5f, -1.1f); - glEnd(); - glRasterPos3d(-a, a, -a); - - glColor3f(0, 0, 1); - glBegin(GL_LINES); - glVertex3f(-1.1f, -1.1f, -1.1f); - glVertex3f(-1.1f, -1.1f, +0.5f); - glEnd(); - glRasterPos3d(-a, -a, a); - - glEnable(GL_TEXTURE_2D); - } - } - - // Draw the cube faces - if (pickMode) { - for (vector::iterator f = m_Faces.begin(); f != m_Faces.end(); f++) { - glColor3ub((*f)->m_PickId, 0, 0); - glBindTexture(GL_TEXTURE_2D, (*f)->m_PickTextureId); - glDrawElements(GL_TRIANGLE_FAN, (*f)->m_VertexCount, GL_UNSIGNED_BYTE, (void*)&m_IndexArray[(*f)->m_FirstVertex]); - } - } - else { - for (int pass = 0; pass < 3; pass++) { - for (vector::iterator f = m_Faces.begin(); f != m_Faces.end(); f++) { - //if (pickMode) { // pick should not be drawn in tree passes - // glColor3ub((*f)->m_PickId, 0, 0); - // glBindTexture(GL_TEXTURE_2D, (*f)->m_PickTextureId); - //} else { - if (pass != (*f)->m_RenderPass) - continue; - QColor& c = (m_HiliteId == (*f)->m_PickId) && (pass < 2) ? m_HiliteColor : (*f)->m_Color; - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); - glBindTexture(GL_TEXTURE_2D, (*f)->m_TextureId); - //} - glDrawElements(GL_TRIANGLE_FAN, (*f)->m_VertexCount, GL_UNSIGNED_BYTE, (void*)&m_IndexArray[(*f)->m_FirstVertex]); - } - } - } - // Draw the rotate buttons - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - if (!pickMode && m_BorderWidth >= 1.0f) { - glDisable(GL_DEPTH_TEST); - glDisable(GL_TEXTURE_2D); - const auto& c = m_BorderColor; - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + // cube borders + glDepthRange(0.09f, 0.9f); // make sure borders and labels are on top glLineWidth(m_BorderWidth); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - for (int pass = 0; pass < 3; pass++) { - for (const auto& f : m_Faces) { - if (pass != f->m_RenderPass) - continue; - if (f->m_TextureId == f->m_PickTextureId) { - if (f->m_PickTexId == TEX_FRONT_FACE || f->m_PickTexId == TEX_EDGE_FACE - || f->m_PickTexId == TEX_CORNER_FACE) { - glBegin(GL_POLYGON); - for (const Vector3f& v : m_VertexArrays2[f->m_PickId]) { - glVertex3f(v[0], v[1], v[2]); - } - glEnd(); - } - } - } + // QColor& cb = m_EmphaseColor; + for (const auto& pair : m_Faces) { + auto f = pair.second; + if (f.type == SHAPE_BUTTON) + continue; + glColor4f(cb.redF(), cb.greenF(), cb.blueF(), cb.alphaF()); + glVertexPointer(3, GL_FLOAT, 0, f.vertexArray.data()); + glDrawArrays(GL_POLYGON, 0, f.vertexArray.size()); } - glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // Label textures + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + float texCoords[] = {0.f,0.f,1.f,0.f,1.f,1.f,0.f,1.f}; + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + QColor& c = m_EmphaseColor; + glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + for (const auto& pair : m_LabelTextures) { + auto f = pair.second; + int pickId = pair.first; + glVertexPointer(3, GL_FLOAT, 0, m_LabelTextures[pickId].vertexArray.data()); + glBindTexture(GL_TEXTURE_2D, f.texture->textureId()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + } - - - glDisable(GL_DEPTH_TEST); - glClear(GL_DEPTH_BUFFER_BIT); - + // Draw the flat buttons + glDisable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0, 1, 1, 0, 0, 1); + glOrtho(0.0, 1.0, 1.0, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - for (vector::iterator b = m_Buttons.begin(); b != m_Buttons.end(); b++) { - if (pickMode) - glColor3ub(*b, 0, 0); + for (const auto& pair : m_Faces) { + auto f = pair.second; + if (f.type != SHAPE_BUTTON) + continue; + auto pickId = pair.first; + if (pickMode) { + glColor3ub(pickId, 0, 0); + } else { - QColor& c = (m_HiliteId == (*b)) ? m_HiliteColor : m_ButtonColor; + QColor& c = m_HiliteId == pickId ? m_HiliteColor : m_BaseColor; glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } - glBindTexture(GL_TEXTURE_2D, m_Textures[*b]); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex3f(0.0f, 1.0f, 0.0f); - glTexCoord2f(1, 0); - glVertex3f(1.0f, 1.0f, 0.0f); - glTexCoord2f(1, 1); - glVertex3f(1.0f, 0.0f, 0.0f); - glTexCoord2f(0, 1); - glVertex3f(0.0f, 0.0f, 0.0f); - glEnd(); - } - - // Draw the view menu icon - if (pickMode) { - glColor3ub(TEX_VIEW_MENU_FACE, 0, 0); - glBindTexture(GL_TEXTURE_2D, m_Textures[TEX_VIEW_MENU_FACE]); - } - else { - if (m_HiliteId == TEX_VIEW_MENU_FACE) { - QColor& c = m_HiliteColor; - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); - glBindTexture(GL_TEXTURE_2D, m_Textures[TEX_VIEW_MENU_FACE]); - - glBegin(GL_QUADS); // DO THIS WITH VERTEX ARRAYS - glTexCoord2f(0, 0); - glVertex3f(0.0f, 1.0f, 0.0f); - glTexCoord2f(1, 0); - glVertex3f(1.0f, 1.0f, 0.0f); - glTexCoord2f(1, 1); - glVertex3f(1.0f, 0.0f, 0.0f); - glTexCoord2f(0, 1); - glVertex3f(0.0f, 0.0f, 0.0f); - glEnd(); + glVertexPointer(3, GL_FLOAT, 0, f.vertexArray.data()); + glDrawArrays(GL_TRIANGLE_FAN, 0, f.vertexArray.size()); + if (!pickMode) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glColor4f(cb.redF(), cb.greenF(), cb.blueF(), cb.alphaF()); + glDrawArrays(GL_POLYGON, 0, f.vertexArray.size()); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } - - QColor& c = m_ButtonColor; - glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); - glBindTexture(GL_TEXTURE_2D, m_Textures[TEX_VIEW_MENU_ICON]); } - glBegin(GL_QUADS); // FIXME do this with vertex arrays - glTexCoord2f(0, 0); - glVertex3f(0.0f, 1.0f, 0.0f); - glTexCoord2f(1, 0); - glVertex3f(1.0f, 1.0f, 0.0f); - glTexCoord2f(1, 1); - glVertex3f(1.0f, 0.0f, 0.0f); - glTexCoord2f(0, 1); - glVertex3f(0.0f, 0.0f, 0.0f); - glEnd(); - - - glPopMatrix(); - // Restore original state. - + glPopMatrix(); glDepthRange(depthrange[0], depthrange[1]); glMatrixMode(GL_PROJECTION); glLoadMatrixd(projectionmatrix); - glPopAttrib(); } int NaviCubeImplementation::pickFace(short x, short y) { - GLubyte pixels[4] = { 0 }; - if (m_PickingFramebuffer) { + GLubyte pixels[4] = {0}; + if (m_PickingFramebuffer && std::abs(x) <= m_CubeWidgetSize / 2 && + std::abs(y) <= m_CubeWidgetSize / 2) { m_PickingFramebuffer->bind(); - glViewport(0, 0, 2 * m_CubeWidgetSize, 2 * m_CubeWidgetSize); + glViewport(0, 0, m_CubeWidgetSize * 2, m_CubeWidgetSize * 2); glLoadIdentity(); glClearColor(0, 0, 0, 1); @@ -1378,22 +875,17 @@ int NaviCubeImplementation::pickFace(short x, short y) { drawNaviCube(true); glFinish(); - - glReadPixels(2 * (x - (m_CubeWidgetPosX - m_CubeWidgetSize / 2)), 2 * (y - (m_CubeWidgetPosY - m_CubeWidgetSize / 2)), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixels); + glReadPixels(2 * x + m_CubeWidgetSize, 2 * y + m_CubeWidgetSize, 1, 1, + GL_RGBA, GL_UNSIGNED_BYTE, &pixels); m_PickingFramebuffer->release(); - - //QImage image = m_PickingFramebuffer->toImage(); - //image.save(QLatin1String("pickimage.png")); } return pixels[3] == 255 ? pixels[0] : 0; } bool NaviCubeImplementation::mousePressed(short x, short y) { m_MouseDown = true; - m_Dragging = false; m_MightDrag = inDragZone(x, y); int pick = pickFace(x, y); - // cerr << enum2str(pick) << endl; setHilite(pick); return pick != 0; } @@ -1455,7 +947,9 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { SbRotation CurrentViewRot = m_View3DInventorViewer->getCameraOrientation(); CurrentViewRot.getValue(ViewRotMatrix); - if (!m_Dragging) { + if (m_Dragging) { + m_Dragging = false; + } else { float rot = 45; float tilt = 90 - Base::toDegrees(atan(sqrt(2.0))); int pick = pickFace(x, y); @@ -1469,7 +963,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { default: return false; break; - case TEX_FRONT: + case PID_FRONT: viewRot = setView(0, 90); // we don't want to dumb rotate to the same view since depending on from where the user clicked on FRONT // we have one of four suitable end positions. @@ -1485,7 +979,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_REAR: + case PID_REAR: viewRot = setView(180, 90); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] > 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) @@ -1496,7 +990,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_LEFT: + case PID_LEFT: viewRot = setView(270, 90); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] > 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) @@ -1507,7 +1001,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_RIGHT: + case PID_RIGHT: viewRot = setView(90, 90); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] < 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) @@ -1518,7 +1012,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_TOP: + case PID_TOP: viewRot = setView(0, 0); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) @@ -1529,7 +1023,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_BOTTOM: + case PID_BOTTOM: viewRot = setView(0, 180); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) @@ -1540,7 +1034,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_FRONT_TOP: + case PID_FRONT_TOP: // set to FRONT then rotate viewRot = setView(0, 90); viewRot = rotateView(viewRot, 1, 45); @@ -1553,7 +1047,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_FRONT_BOTTOM: + case PID_FRONT_BOTTOM: // set to FRONT then rotate viewRot = setView(0, 90); viewRot = rotateView(viewRot, 1, -45); @@ -1566,7 +1060,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_REAR_BOTTOM: + case PID_REAR_BOTTOM: // set to REAR then rotate viewRot = setView(180, 90); viewRot = rotateView(viewRot, 1, -45); @@ -1579,7 +1073,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_REAR_TOP: + case PID_REAR_TOP: // set to REAR then rotate viewRot = setView(180, 90); viewRot = rotateView(viewRot, 1, 45); @@ -1592,7 +1086,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_FRONT_LEFT: + case PID_FRONT_LEFT: // set to FRONT then rotate viewRot = setView(0, 90); viewRot = rotateView(viewRot, 0, 45); @@ -1605,7 +1099,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_FRONT_RIGHT: + case PID_FRONT_RIGHT: // set to FRONT then rotate viewRot = setView(0, 90); viewRot = rotateView(viewRot, 0, -45); @@ -1618,7 +1112,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_REAR_RIGHT: + case PID_REAR_RIGHT: // set to REAR then rotate viewRot = setView(180, 90); viewRot = rotateView(viewRot, 0, 45); @@ -1631,7 +1125,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_REAR_LEFT: + case PID_REAR_LEFT: // set to REAR then rotate viewRot = setView(180, 90); viewRot = rotateView(viewRot, 0, -45); @@ -1642,7 +1136,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { else if (ViewRotMatrix[0][2] < 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) viewRot = rotateView(viewRot, 2, 90); break; - case TEX_TOP_LEFT: + case PID_TOP_LEFT: // set to LEFT then rotate viewRot = setView(270, 90); viewRot = rotateView(viewRot, 1, 45); @@ -1655,7 +1149,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_TOP_RIGHT: + case PID_TOP_RIGHT: // set to RIGHT then rotate viewRot = setView(90, 90); viewRot = rotateView(viewRot, 1, 45); @@ -1668,7 +1162,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_BOTTOM_RIGHT: + case PID_BOTTOM_RIGHT: // set to RIGHT then rotate viewRot = setView(90, 90); viewRot = rotateView(viewRot, 1, -45); @@ -1681,7 +1175,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, -90); } break; - case TEX_BOTTOM_LEFT: + case PID_BOTTOM_LEFT: // set to LEFT then rotate viewRot = setView(270, 90); viewRot = rotateView(viewRot, 1, -45); @@ -1694,7 +1188,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 2, 90); } break; - case TEX_BOTTOM_LEFT_FRONT: + case PID_FRONT_BOTTOM_LEFT: viewRot = setView(rot - 90, 90 + tilt); // we have 3 possible end states: // - z-axis is not rotated larger than 120 deg from (0, 1, 0) -> we are already there @@ -1707,7 +1201,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, 120, SbVec3f(1, 1, 1)); } break; - case TEX_BOTTOM_FRONT_RIGHT: + case PID_FRONT_BOTTOM_RIGHT: viewRot = setView(90 + rot - 90, 90 + tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) @@ -1716,7 +1210,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, -120, SbVec3f(-1, 1, 1)); } break; - case TEX_BOTTOM_RIGHT_REAR: + case PID_REAR_BOTTOM_RIGHT: viewRot = setView(180 + rot - 90, 90 + tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) @@ -1725,7 +1219,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, 120, SbVec3f(-1, -1, 1)); } break; - case TEX_BOTTOM_REAR_LEFT: + case PID_REAR_BOTTOM_LEFT: viewRot = setView(270 + rot - 90, 90 + tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) @@ -1734,7 +1228,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, -120, SbVec3f(1, -1, 1)); } break; - case TEX_TOP_RIGHT_FRONT: + case PID_FRONT_TOP_RIGHT: viewRot = setView(rot, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) @@ -1743,7 +1237,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, 120, SbVec3f(-1, 1, -1)); } break; - case TEX_TOP_FRONT_LEFT: + case PID_FRONT_TOP_LEFT: viewRot = setView(rot - 90, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) @@ -1752,7 +1246,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, -120, SbVec3f(1, 1, -1)); } break; - case TEX_TOP_LEFT_REAR: + case PID_REAR_TOP_LEFT: viewRot = setView(rot - 180, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) @@ -1761,7 +1255,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, 120, SbVec3f(1, -1, -1)); } break; - case TEX_TOP_REAR_RIGHT: + case PID_REAR_TOP_RIGHT: viewRot = setView(rot - 270, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) @@ -1770,28 +1264,28 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { viewRot = rotateView(viewRot, 0, -120, SbVec3f(-1, -1, -1)); } break; - case TEX_ARROW_LEFT: + case PID_ARROW_LEFT: viewRot = rotateView(viewRot, DIR_OUT, rotStepAngle); break; - case TEX_ARROW_RIGHT: + case PID_ARROW_RIGHT: viewRot = rotateView(viewRot, DIR_OUT, -rotStepAngle); break; - case TEX_ARROW_WEST: + case PID_ARROW_WEST: viewRot = rotateView(viewRot, DIR_UP, -rotStepAngle); break; - case TEX_ARROW_EAST: + case PID_ARROW_EAST: viewRot = rotateView(viewRot, DIR_UP, rotStepAngle); break; - case TEX_ARROW_NORTH: + case PID_ARROW_NORTH: viewRot = rotateView(viewRot, DIR_RIGHT, -rotStepAngle); break; - case TEX_ARROW_SOUTH: + case PID_ARROW_SOUTH: viewRot = rotateView(viewRot, DIR_RIGHT, rotStepAngle); break; - case TEX_DOT_BACKSIDE: + case PID_DOT_BACKSIDE: viewRot = rotateView(viewRot, DIR_UP, 180); break; - case TEX_VIEW_MENU_FACE: + case PID_VIEW_MENU: handleMenu(); applyRotation = false; break; @@ -1806,33 +1300,31 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { void NaviCubeImplementation::setHilite(int hilite) { if (hilite != m_HiliteId) { m_HiliteId = hilite; - //cerr << "m_HiliteFace " << m_HiliteId << endl; m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); } } bool NaviCubeImplementation::inDragZone(short x, short y) { - int dx = x - m_CubeWidgetPosX; - int dy = y - m_CubeWidgetPosY; int limit = m_CubeWidgetSize / 4; - return abs(dx) < limit && abs(dy) < limit; + return std::abs(x) < limit && std::abs(y) < limit; } bool NaviCubeImplementation::mouseMoved(short x, short y) { - setHilite(pickFace(x, y)); + if (!m_Dragging) + setHilite(pickFace(x, y)); - if (m_MouseDown) { - if (m_MightDrag && !m_Dragging && !inDragZone(x, y)) + if (m_MouseDown && m_Draggable) { + if (m_MightDrag && !m_Dragging) { m_Dragging = true; - if (m_Dragging) { setHilite(0); - SbVec2s view = m_View3DInventorViewer->getSoRenderManager()->getSize(); - int width = view[0]; - int height = view[1]; - int len = m_CubeWidgetSize / 2; - m_CubeWidgetPosX = std::min(std::max(static_cast(x), len), width - len); - m_CubeWidgetPosY = std::min(std::max(static_cast(y), len), height - len); - this->m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); + } + if (m_Dragging && (std::abs(x) || std::abs(y))) { + float newX = m_RelPos[0] + (float)(x) / m_PosAreaSize[0]; + float newY = m_RelPos[1] + (float)(y) / m_PosAreaSize[1]; + m_RelPos[0] = std::min(std::max(newX, 0.0f), 1.0f); + m_RelPos[1] = std::min(std::max(newY, 0.0f), 1.0f); + + m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); return true; } } @@ -1842,23 +1334,19 @@ bool NaviCubeImplementation::mouseMoved(short x, short y) { bool NaviCubeImplementation::processSoEvent(const SoEvent* ev) { short x, y; ev->getPosition().getValue(x, y); - // FIXME find out why do we need to hack the cursor position to get - // 2019-02-17 - // The above comment is truncated; don't know what it's about - // The two hacked lines changing the cursor position are responsible for - // parts of the navigational cluster not being active. - // Commented them out and everything seems to be working -// y += 4; -// x -= 2; + // translate to internal cube center based coordinates + short rx = x - (short)(m_PosAreaSize[0]*m_RelPos[0]) - m_PosAreaBase[0]; + short ry = y - (short)(m_PosAreaSize[1]*m_RelPos[1]) - m_PosAreaBase[1]; if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) { const auto mbev = static_cast(ev); if (mbev->isButtonPressEvent(mbev, SoMouseButtonEvent::BUTTON1)) - return mousePressed(x, y); + return mousePressed(rx, ry); if (mbev->isButtonReleaseEvent(mbev, SoMouseButtonEvent::BUTTON1)) - return mouseReleased(x, y); + return mouseReleased(rx, ry); + } + if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) { + return mouseMoved(rx, ry); } - if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) - return mouseMoved(x, y); return false; } @@ -1871,91 +1359,41 @@ void NaviCube::setNaviCubeCommands(const std::vector& cmd) NaviCubeImplementation::m_commands = cmd; } -void NaviCube::setNaviCubeLabels(const std::vector& labels) -{ - NaviCubeImplementation::m_labels = labels; -} +DEF_STD_CMD_AC(NaviCubeDraggableCmd) -DEF_3DV_CMD(ViewIsometricCmd) -ViewIsometricCmd::ViewIsometricCmd() - : Command("ViewIsometricCmd") +NaviCubeDraggableCmd::NaviCubeDraggableCmd() + : Command("NaviCubeDraggableCmd") { sGroup = ""; - sMenuText = QT_TR_NOOP("Isometric"); - sToolTipText = QT_TR_NOOP("Set NaviCube to Isometric mode"); + sMenuText = QT_TR_NOOP("Movable navigation cube"); + sToolTipText = QT_TR_NOOP("Drag and place NaviCube"); sWhatsThis = ""; sStatusTip = sToolTipText; - sPixmap = ""; - sAccel = ""; eType = Alter3DView; } - -void ViewIsometricCmd::activated(int iMsg) +void NaviCubeDraggableCmd::activated(int iMsg) { - Q_UNUSED(iMsg); - Command::doCommand(Command::Gui, "Gui.activeDocument().activeView().viewIsometric()"); + auto view = qobject_cast(getMainWindow()->activeWindow()); + view->getViewer()->getNaviCube()->setDraggable(iMsg == 1 ? true : false); } - -DEF_3DV_CMD(ViewOrthographicCmd) -ViewOrthographicCmd::ViewOrthographicCmd() - : Command("ViewOrthographicCmd") +bool NaviCubeDraggableCmd::isActive(void) { - sGroup = ""; - sMenuText = QT_TR_NOOP("Orthographic"); - sToolTipText = QT_TR_NOOP("Set View to Orthographic mode"); - sWhatsThis = ""; - sStatusTip = sToolTipText; - sPixmap = ""; - sAccel = ""; - eType = Alter3DView; + Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); + if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + bool check = _pcAction->isChecked(); + auto view = qobject_cast(getMainWindow()->activeWindow()); + bool mode = view->getViewer()->getNaviCube()->isDraggable(); + if (mode != check) + _pcAction->setChecked(mode); + return true; + } + return false; } - -void ViewOrthographicCmd::activated(int iMsg) +Gui::Action * NaviCubeDraggableCmd::createAction() { - Q_UNUSED(iMsg); - Command::doCommand(Command::Gui, "Gui.activeDocument().activeView().setCameraType(\"Orthographic\")"); -} - -DEF_3DV_CMD(ViewPerspectiveCmd) - -ViewPerspectiveCmd::ViewPerspectiveCmd() - : Command("ViewPerspectiveCmd") -{ - sGroup = ""; - sMenuText = QT_TR_NOOP("Perspective"); - sToolTipText = QT_TR_NOOP("Set View to Perspective mode"); - sWhatsThis = ""; - sStatusTip = sToolTipText; - sPixmap = ""; - sAccel = ""; - eType = Alter3DView; -} - -void ViewPerspectiveCmd::activated(int iMsg) -{ - Q_UNUSED(iMsg); - Command::doCommand(Command::Gui, "Gui.activeDocument().activeView().setCameraType(\"Perspective\")"); -} - -DEF_3DV_CMD(ViewZoomToFitCmd) - -ViewZoomToFitCmd::ViewZoomToFitCmd() - : Command("ViewZoomToFit") -{ - sGroup = ""; - sMenuText = QT_TR_NOOP("Zoom to fit"); - sToolTipText = QT_TR_NOOP("Zoom so that model fills the view"); - sWhatsThis = ""; - sStatusTip = sToolTipText; - sPixmap = ""; - sAccel = ""; - eType = Alter3DView; -} - -void ViewZoomToFitCmd::activated(int iMsg) -{ - Q_UNUSED(iMsg); - Command::doCommand(Command::Gui, "Gui.SendMsgToActiveView(\"ViewFit\")"); + Gui::Action *pcAction = Command::createAction(); + pcAction->setCheckable(true); + return pcAction; } @@ -1967,19 +1405,18 @@ QMenu* NaviCubeImplementation::createNaviCubeMenu() { static bool init = true; if (init) { init = false; - rcCmdMgr.addCommand(new ViewOrthographicCmd); - rcCmdMgr.addCommand(new ViewPerspectiveCmd); - rcCmdMgr.addCommand(new ViewIsometricCmd); - rcCmdMgr.addCommand(new ViewZoomToFitCmd); + rcCmdMgr.addCommand(new NaviCubeDraggableCmd); } vector commands = NaviCubeImplementation::m_commands; if (commands.empty()) { - commands.emplace_back("ViewOrthographicCmd"); - commands.emplace_back("ViewPerspectiveCmd"); - commands.emplace_back("ViewIsometricCmd"); + commands.emplace_back("Std_OrthographicCamera"); + commands.emplace_back("Std_PerspectiveCamera"); + commands.emplace_back("Std_ViewIsometric"); commands.emplace_back("Separator"); - commands.emplace_back("ViewZoomToFit"); + commands.emplace_back("Std_ViewFitAll"); + commands.emplace_back("Separator"); + commands.emplace_back("NaviCubeDraggableCmd"); } for (const auto & command : commands) { diff --git a/src/Gui/NaviCube.h b/src/Gui/NaviCube.h index dff5af5a5a..c18701c639 100644 --- a/src/Gui/NaviCube.h +++ b/src/Gui/NaviCube.h @@ -49,21 +49,25 @@ public: void createContextMenu(const std::vector& cmd); bool processSoEvent(const SoEvent* ev); void setCorner(Corner); + void setOffset(int x, int y); + bool isDraggable(); + void setDraggable(bool draggable); void setSize(int size); + void setChamfer(float size); void setNaviRotateToNearest(bool toNearest); void setNaviStepByTurn(int steps); void setFont(std::string font); - void setFontSize(int size); - void setTextColor(QColor TextColor); - void setFrontColor(QColor FrontColor); + void setFontWeight(int weight); + void setFontStretch(int stretch); + void setFontZoom(float zoom); + void setBaseColor(QColor TextColor); + void setEmphaseColor(QColor ButtonColor); void setHiliteColor(QColor HiliteColor); - void setButtonColor(QColor ButtonColor); void setBorderWidth(double BorderWidth); - void setBorderColor(QColor BorderColor); - static QString getDefaultSansserifFont(); - int getDefaultFontSize(); + void setShowCS(bool showCS); + // front, top, right, rear, bottom, left + void setNaviCubeLabels(const std::vector& labels); static void setNaviCubeCommands(const std::vector& cmd); - static void setNaviCubeLabels(const std::vector& labels); private: NaviCubeImplementation* m_NaviCubeImplementation; diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 196a22ad1d..060e6cce16 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -145,7 +145,6 @@ View3DInventor::~View3DInventor() } viewSettings.reset(); - naviSettings.reset(); //If we destroy this viewer by calling 'delete' directly the focus proxy widget which is defined //by a widget in SoQtViewer isn't reset. This widget becomes a dangling pointer and makes diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index ad41a2cefe..bbca1f9528 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1194,19 +1194,11 @@ void View3DInventorViewer::setNaviCubeCorner(int c) naviCube->setCorner(static_cast(c)); } -NaviCube* View3DInventorViewer::getNavigationCube() const +NaviCube* View3DInventorViewer::getNaviCube() const { return naviCube; } -void View3DInventorViewer::updateNavigationCube() -{ - if (naviCube) { - delete naviCube; - naviCube = new NaviCube(this); - } -} - void View3DInventorViewer::setAxisCross(bool on) { SoNode* scene = getSceneGraph(); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index c5d951e694..1eda1bce60 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -417,8 +417,7 @@ public: void setEnabledNaviCube(bool b); bool isEnabledNaviCube() const; void setNaviCubeCorner(int); - NaviCube* getNavigationCube() const; - void updateNavigationCube(); + NaviCube* getNaviCube() const; void setEnabledVBO(bool b); bool isEnabledVBO() const; void setRenderCache(int); diff --git a/src/Gui/View3DSettings.cpp b/src/Gui/View3DSettings.cpp index 61e5d57529..fb13bde4dc 100644 --- a/src/Gui/View3DSettings.cpp +++ b/src/Gui/View3DSettings.cpp @@ -438,65 +438,121 @@ NaviCubeSettings::NaviCubeSettings(ParameterGrp::handle hGrp, : hGrp(hGrp) , _viewer(view) { - hGrp->Attach(this); + connectParameterChanged = hGrp->Manager()->signalParamChanged.connect( + [this](ParameterGrp*, ParameterGrp::ParamType, const char *Name, const char *) { + parameterChanged(Name); + }); + } NaviCubeSettings::~NaviCubeSettings() { - hGrp->Detach(this); + connectParameterChanged.disconnect(); +} +QString NaviCubeSettings::getDefaultSansserifFont() +{ + // "FreeCAD NaviCube" family susbtitutions are set in MainWindow::MainWindow + QFont font(QStringLiteral("FreeCAD NaviCube")); + font.setStyleHint(QFont::SansSerif); + // QFontInfo is required to get the actually matched font family + return QFontInfo(font).family(); + // return QStringLiteral("FreeCAD NaviCube"); } - void NaviCubeSettings::applySettings() { - OnChange(*hGrp, "CornerNaviCube"); + parameterChanged("BaseColor"); + parameterChanged("EmphaseColor"); + parameterChanged("HiliteColor"); + parameterChanged("CornerNaviCube"); + parameterChanged("CubeSize"); + parameterChanged("ChamferSize"); + parameterChanged("NaviRotateToNearest"); + parameterChanged("NaviStepByTurn"); + parameterChanged("BorderWidth"); + parameterChanged("FontZoom"); + parameterChanged("FontString"); + parameterChanged("FontWeight"); + parameterChanged("FontStretch"); + parameterChanged("ShowCS"); + parameterChanged("TextFront"); // Updates all labels } -void NaviCubeSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason) +void NaviCubeSettings::parameterChanged(const char* Name) { - const ParameterGrp& rGrp = static_cast(rCaller); - if (strcmp(Reason, "CornerNaviCube") == 0) { - _viewer->setNaviCubeCorner(rGrp.GetInt("CornerNaviCube", 1)); + if (Name == nullptr) + return; + NaviCube* nc = _viewer->getNaviCube(); + if (strcmp(Name, "CornerNaviCube") == 0) { + nc->setCorner(static_cast(hGrp->GetInt("CornerNaviCube", 1))); } - else if (strcmp(Reason, "CubeSize") == 0) { - _viewer->getNavigationCube()->setSize(rGrp.GetInt("CubeSize", 132)); + else if (strcmp(Name, "OffsetX") == 0 || strcmp(Name, "OffsetY") == 0) { + nc->setOffset(hGrp->GetInt("OffsetX", 0), hGrp->GetInt("OffsetY", 0)); } - else if (strcmp(Reason, "NaviRotateToNearest") == 0) { - _viewer->getNavigationCube()->setNaviRotateToNearest( - rGrp.GetBool("NaviRotateToNearest", true)); + else if (strcmp(Name, "ChamferSize") == 0) { + nc->setChamfer(hGrp->GetFloat("ChamferSize", 0.12f)); } - else if (strcmp(Reason, "NaviStepByTurn") == 0) { - _viewer->getNavigationCube()->setNaviStepByTurn(rGrp.GetInt("NaviStepByTurn", 8)); + else if (strcmp(Name, "CubeSize") == 0) { + nc->setSize(hGrp->GetInt("CubeSize", 132)); } - else if (strcmp(Reason, "FontSize") == 0) { - _viewer->getNavigationCube()->setFontSize( - rGrp.GetInt("FontSize", _viewer->getNavigationCube()->getDefaultFontSize())); + else if (strcmp(Name, "NaviRotateToNearest") == 0) { + nc->setNaviRotateToNearest(hGrp->GetBool("NaviRotateToNearest", true)); } - else if (strcmp(Reason, "FontString") == 0) { - std::string font = rGrp.GetASCII( - "FontString", NaviCube::getDefaultSansserifFont().toStdString().c_str()); - _viewer->getNavigationCube()->setFont(font); + else if (strcmp(Name, "NaviStepByTurn") == 0) { + nc->setNaviStepByTurn(hGrp->GetInt("NaviStepByTurn", 8)); } - else if (strcmp(Reason, "TextColor") == 0) { - unsigned long col = rGrp.GetUnsigned("TextColor", 255); - _viewer->getNavigationCube()->setTextColor(App::Color::fromPackedRGBA(col)); + else if (strcmp(Name, "FontZoom") == 0) { + nc->setFontZoom(hGrp->GetFloat("FontZoom", 0.3)); } - else if (strcmp(Reason, "FrontColor") == 0) { - unsigned long col = rGrp.GetUnsigned("FrontColor", 3806916544); - _viewer->getNavigationCube()->setFrontColor(App::Color::fromPackedRGBA(col)); + else if (strcmp(Name, "FontString") == 0) { + std::string font = + hGrp->GetASCII("FontString", getDefaultSansserifFont().toStdString().c_str()); + nc->setFont(font); } - else if (strcmp(Reason, "HiliteColor") == 0) { - unsigned long col = rGrp.GetUnsigned("HiliteColor", 2867003391); - _viewer->getNavigationCube()->setHiliteColor(App::Color::fromPackedRGBA(col)); + else if (strcmp(Name, "FontWeight") == 0) { + nc->setFontWeight(hGrp->GetInt("FontWeight", 0)); } - else if (strcmp(Reason, "ButtonColor") == 0) { - unsigned long col = rGrp.GetUnsigned("ButtonColor", 3806916480); - _viewer->getNavigationCube()->setButtonColor(App::Color::fromPackedRGBA(col)); + else if (strcmp(Name, "FontStretch") == 0) { + nc->setFontStretch(hGrp->GetInt("FontStretch", 0)); } - else if (strcmp(Reason, "BorderWidth") == 0) { - _viewer->getNavigationCube()->setBorderWidth(rGrp.GetFloat("BorderWidth", 1.1)); + else if (strcmp(Name, "BaseColor") == 0) { + unsigned long col = hGrp->GetUnsigned("BaseColor", 3806916544); + nc->setBaseColor(App::Color::fromPackedRGBA(col)); + // update default contrast colors + parameterChanged("EmphaseColor"); + } + else if (strcmp(Name, "EmphaseColor") == 0) { + App::Color bc((uint32_t)hGrp->GetUnsigned("BaseColor", 3806916544)); + unsigned long d = bc.r + bc.g + bc.b >= 1.5f ? 255 : 4294967295; + unsigned long col = hGrp->GetUnsigned("EmphaseColor", d); + nc->setEmphaseColor(App::Color::fromPackedRGBA(col)); } - else if (strcmp(Reason, "BorderColor") == 0) { - unsigned long col = rGrp.GetUnsigned("BorderColor", 842150655); - _viewer->getNavigationCube()->setBorderColor(App::Color::fromPackedRGBA(col)); + else if (strcmp(Name, "HiliteColor") == 0) { + unsigned long col = hGrp->GetUnsigned("HiliteColor", 2867003391); + nc->setHiliteColor(App::Color::fromPackedRGBA(col)); } + else if (strcmp(Name, "BorderWidth") == 0) { + nc->setBorderWidth(hGrp->GetFloat("BorderWidth", 1.1)); + } + else if (strcmp(Name, "ShowCS") == 0) { + nc->setShowCS(hGrp->GetBool("ShowCS", 1)); + } + else if (strcmp(Name, "TextTop") == 0 || strcmp(Name, "TextBottom") == 0 + || strcmp(Name, "TextFront") == 0 || strcmp(Name, "TextRear") == 0 + || strcmp(Name, "TextLeft") == 0 || strcmp(Name, "TextRight") == 0) { + std::vector labels; + QByteArray frontByteArray = tr("FRONT").toUtf8(); + labels.push_back(hGrp->GetASCII("TextFront", frontByteArray.constData())); + QByteArray topByteArray = tr("TOP").toUtf8(); + labels.push_back(hGrp->GetASCII("TextTop", topByteArray.constData())); + QByteArray rightByteArray = tr("RIGHT").toUtf8(); + labels.push_back(hGrp->GetASCII("TextRight", rightByteArray.constData())); + QByteArray rearByteArray = tr("REAR").toUtf8(); + labels.push_back(hGrp->GetASCII("TextRear", rearByteArray.constData())); + QByteArray bottomByteArray = tr("BOTTOM").toUtf8(); + labels.push_back(hGrp->GetASCII("TextBottom", bottomByteArray.constData())); + QByteArray leftByteArray = tr("LEFT").toUtf8(); + labels.push_back(hGrp->GetASCII("TextLeft", leftByteArray.constData())); + nc->setNaviCubeLabels(labels); + } + _viewer->getSoRenderManager()->scheduleRedraw(); } diff --git a/src/Gui/View3DSettings.h b/src/Gui/View3DSettings.h index dd8a224c41..7c52247405 100644 --- a/src/Gui/View3DSettings.h +++ b/src/Gui/View3DSettings.h @@ -24,6 +24,7 @@ #define GUI_VIEW3DSETTINGS_H #include +#include namespace Gui { class View3DInventorViewer; @@ -51,19 +52,20 @@ private: std::vector _viewers; }; -class NaviCubeSettings : public ParameterGrp::ObserverType +class NaviCubeSettings { + Q_DECLARE_TR_FUNCTIONS(NaviCubeSettings) public: NaviCubeSettings(ParameterGrp::handle hGrp, View3DInventorViewer *); - ~NaviCubeSettings() override; + ~NaviCubeSettings(); - /// Observer message from the ParameterGrp - void OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason) override; void applySettings(); - + static QString getDefaultSansserifFont(); private: + void parameterChanged(ParameterGrp::MessageType pName); ParameterGrp::handle hGrp; View3DInventorViewer * _viewer; + boost::signals2::connection connectParameterChanged; }; } // namespace Gui From 0c20d6f1a5f26c6eddc1be9b5773dd998a2eeb53 Mon Sep 17 00:00:00 2001 From: Jolbas <39026960+Jolbas@users.noreply.github.com> Date: Mon, 24 Apr 2023 07:21:20 +0200 Subject: [PATCH 2/2] NavCube adjustment Use enum class and fine change to camel case. Tuned label positions to make one letter labels align better --- src/Gui/NaviCube.cpp | 642 ++++++++++++++++++++++--------------------- src/Gui/NaviCube.h | 2 +- 2 files changed, 336 insertions(+), 308 deletions(-) diff --git a/src/Gui/NaviCube.cpp b/src/Gui/NaviCube.cpp index 7c6172f13c..6058237990 100644 --- a/src/Gui/NaviCube.cpp +++ b/src/Gui/NaviCube.cpp @@ -63,16 +63,6 @@ using namespace Gui; -struct Face { - int type; - vector vertexArray; -}; -struct LabelTexture { - vector vertexArray; - qreal fontSize; - QOpenGLTexture *texture = nullptr; - string label; -}; class NaviCubeImplementation { @@ -90,92 +80,91 @@ public: void setSize(int size); private: + enum class PickId { + None, + Front, + Top, + Right, + Rear, + Bottom, + Left, + FrontTop, + FrontBottom, + FrontRight, + FrontLeft, + RearTop, + RearBottom, + RearRight, + RearLeft, + TopRight, + TopLeft, + BottomRight, + BottomLeft, + FrontTopRight, + FrontTopLeft, + FrontBottomRight, + FrontBottomLeft, + RearTopRight, + RearTopLeft, + RearBottomRight, + RearBottomLeft, + ArrowNorth, + ArrowSouth, + ArrowEast, + ArrowWest, + ArrowRight, + ArrowLeft, + DotBackside, + ViewMenu + }; + enum class DirId{ + Custom, Up, Right, Out + }; + enum class ShapeId{ + None, Main, Edge, Corner, Button + }; + struct Face { + ShapeId type; + vector vertexArray; + }; + struct LabelTexture { + vector vertexArray; + qreal fontSize; + QOpenGLTexture *texture = nullptr; + string label; + }; bool mousePressed(short x, short y); bool mouseReleased(short x, short y); bool mouseMoved(short x, short y); - int pickFace(short x, short y); + PickId pickFace(short x, short y); bool inDragZone(short x, short y); void prepare(); void handleResize(); void handleMenu(); - void setHilite(int); + void setHilite(PickId); - void addCubeFace(const Vector3f&, const Vector3f&, int, int); - - void addButtonFaceTex(QtGLWidget*, int); - void addButtonFace(int); + void addCubeFace(const Vector3f&, const Vector3f&, ShapeId, PickId); + void addButtonFace(PickId); SbRotation setView(float, float) const; - SbRotation rotateView(SbRotation, int axis, float rotAngle, SbVec3f customAxis = SbVec3f(0, 0, 0)) const; + SbRotation rotateView(SbRotation, DirId, float, SbVec3f customAxis = SbVec3f(0, 0, 0)) const; void rotateView(const SbRotation&); QString str(const char* str); QMenu* createNaviCubeMenu(); - -public: - enum { - PID_NONE, - PID_FRONT, - PID_TOP, - PID_RIGHT, - PID_REAR, - PID_BOTTOM, - PID_LEFT, - PID_FRONT_TOP, - PID_FRONT_BOTTOM, - PID_FRONT_RIGHT, - PID_FRONT_LEFT, - PID_REAR_TOP, - PID_REAR_BOTTOM, - PID_REAR_RIGHT, - PID_REAR_LEFT, - PID_TOP_RIGHT, - PID_TOP_LEFT, - PID_BOTTOM_RIGHT, - PID_BOTTOM_LEFT, - PID_FRONT_TOP_RIGHT, - PID_FRONT_TOP_LEFT, - PID_FRONT_BOTTOM_RIGHT, - PID_FRONT_BOTTOM_LEFT, - PID_REAR_TOP_RIGHT, - PID_REAR_TOP_LEFT, - PID_REAR_BOTTOM_RIGHT, - PID_REAR_BOTTOM_LEFT, - PID_ARROW_NORTH, - PID_ARROW_SOUTH, - PID_ARROW_EAST, - PID_ARROW_WEST, - PID_ARROW_RIGHT, - PID_ARROW_LEFT, - PID_DOT_BACKSIDE, - PID_VIEW_MENU - }; - enum { - DIR_UP, DIR_RIGHT, DIR_OUT - }; - enum { - SHAPE_NONE, SHAPE_MAIN, SHAPE_EDGE, SHAPE_CORNER, SHAPE_BUTTON - }; - Gui::View3DInventorViewer* m_View3DInventorViewer; void drawNaviCube(bool picking); + +public: + int m_CubeWidgetSize = 132; - SbVec2f m_RelPos = SbVec2f(1.0f,1.0f); - SbVec2s m_ViewSize = SbVec2s(0,0); - SbVec2s m_PosAreaBase = SbVec2s(0,0); - SbVec2s m_PosAreaSize = SbVec2s(0,0); - SbVec2s m_PosOffset = SbVec2s(0,0); QColor m_BaseColor; QColor m_EmphaseColor; QColor m_HiliteColor; bool m_ShowCS = true; - int m_HiliteId = 0; - bool m_MouseDown = false; - bool m_Dragging = false; - bool m_Draggable = false; - bool m_MightDrag = false; + PickId m_HiliteId = PickId::None; double m_BorderWidth = 1.1; bool m_RotateToNearest = true; int m_NaviStepByTurn = 8; @@ -184,14 +173,27 @@ public: std::string m_TextFont; int m_FontWeight = 0; int m_FontStretch = 0; - - QtGLFramebufferObject* m_PickingFramebuffer; + SbVec2s m_PosOffset = SbVec2s(0,0); bool m_Prepared = false; - - map m_Faces; - map m_LabelTextures; static vector m_commands; + bool m_Draggable = false; + SbVec2s m_ViewSize = SbVec2s(0,0); + +private: + bool m_MouseDown = false; + bool m_Dragging = false; + bool m_MightDrag = false; + + SbVec2f m_RelPos = SbVec2f(1.0f,1.0f); + SbVec2s m_PosAreaBase = SbVec2s(0,0); + SbVec2s m_PosAreaSize = SbVec2s(0,0); + + QtGLFramebufferObject* m_PickingFramebuffer; + Gui::View3DInventorViewer* m_View3DInventorViewer; + + map m_Faces; + map m_LabelTextures; QMenu* m_Menu; }; @@ -311,12 +313,12 @@ void NaviCube::setNaviCubeLabels(const std::vector& labels) } void NaviCubeImplementation::setLabels(const std::vector& labels) { - m_LabelTextures[PID_FRONT].label = labels[0]; - m_LabelTextures[PID_TOP].label = labels[1]; - m_LabelTextures[PID_RIGHT].label = labels[2]; - m_LabelTextures[PID_REAR].label = labels[3]; - m_LabelTextures[PID_BOTTOM].label = labels[4]; - m_LabelTextures[PID_LEFT].label = labels[5]; + m_LabelTextures[PickId::Front].label = labels[0]; + m_LabelTextures[PickId::Top].label = labels[1]; + m_LabelTextures[PickId::Right].label = labels[2]; + m_LabelTextures[PickId::Rear].label = labels[3]; + m_LabelTextures[PickId::Bottom].label = labels[4]; + m_LabelTextures[PickId::Left].label = labels[5]; m_Prepared = false; } @@ -365,9 +367,31 @@ auto convertWeights = [](int weight) -> QFont::Weight { return QFont::Thin; }; +int imageVerticalBalance(QImage p, int sizeHint) { + int h = p.height(); + int startRow = (h - sizeHint) / 2; + bool done = false; + int x, bottom, top; + for (top = startRow; top < h; top++){ + for (x = 0; x < p.width(); x++){ + if (qAlpha(p.pixel(x, top))) { + done = true; + break; + } + } + if (done) break; + } + for (bottom = startRow; bottom < h; bottom++) { + for (x = 0; x < p.width(); x++){ + if (qAlpha(p.pixel(x, h-1-bottom))) + return (bottom-top)/2; + } + } + return 0; +} void NaviCubeImplementation::createCubeFaceTextures() { - int texSize = 128; // Works well for the max cube size 1024 + int texSize = 192; // Works well for the max cube size 1024 // find font sizes QFont font; QString fontString = QString::fromStdString(m_TextFont); @@ -382,11 +406,12 @@ void NaviCubeImplementation::createCubeFaceTextures() { QFontMetrics fm(font); qreal minFontSize = texSize; qreal maxFontSize = 0.; - vector mains = {PID_FRONT, PID_TOP, PID_RIGHT, PID_REAR, PID_BOTTOM, PID_LEFT}; - for (int pickId : mains) { + vector mains = {PickId::Front, PickId::Top, PickId::Right, PickId::Rear, PickId::Bottom, PickId::Left}; + for (PickId pickId : mains) { auto t = QString::fromUtf8(m_LabelTextures[pickId].label.c_str()); - float textlen = fm.horizontalAdvance(t); - m_LabelTextures[pickId].fontSize = texSize * texSize / textlen; + QRect br = fm.boundingRect(t); + float scale = (float)texSize / max(br.width(),br.height()); + m_LabelTextures[pickId].fontSize = texSize * scale; minFontSize = std::min(minFontSize, m_LabelTextures[pickId].fontSize); maxFontSize = std::max(maxFontSize, m_LabelTextures[pickId].fontSize); } @@ -395,22 +420,25 @@ void NaviCubeImplementation::createCubeFaceTextures() { else { maxFontSize = minFontSize * std::pow(2.0, m_FontZoom); } - for (int pickId : mains) { - m_LabelTextures[pickId].fontSize = std::min(m_LabelTextures[pickId].fontSize, maxFontSize); + for (PickId pickId : mains) { QImage image(texSize, texSize, QImage::Format_ARGB32); image.fill(qRgba(255, 255, 255, 0)); - QPainter paint; - paint.begin(&image); - paint.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - paint.setPen(Qt::white); if (m_LabelTextures[pickId].fontSize > 0.5) { - QString text = QString::fromUtf8(m_LabelTextures[pickId].label.c_str()); // 5% margin looks nice and prevents some artifacts - font.setPointSizeF(m_LabelTextures[pickId].fontSize * 0.9); + font.setPointSizeF(std::min(m_LabelTextures[pickId].fontSize, maxFontSize)*0.9); + QPainter paint; + paint.begin(&image); + paint.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + paint.setPen(Qt::white); + QString text = QString::fromUtf8(m_LabelTextures[pickId].label.c_str()); paint.setFont(font); paint.drawText(QRect(0, 0, texSize, texSize), Qt::AlignCenter, text); + int offset = imageVerticalBalance(image, font.pointSize()); + image.fill(qRgba(255, 255, 255, 0)); + paint.drawText(QRect(0, offset, texSize, texSize), Qt::AlignCenter, text); + paint.end(); } - paint.end(); + if (m_LabelTextures[pickId].texture) { delete m_LabelTextures[pickId].texture; } @@ -421,7 +449,7 @@ void NaviCubeImplementation::createCubeFaceTextures() { } } -void NaviCubeImplementation::addButtonFace(int pickId) +void NaviCubeImplementation::addButtonFace(PickId pickId) { if (m_Faces[pickId].vertexArray.size()) m_Faces[pickId].vertexArray.clear(); @@ -433,8 +461,8 @@ void NaviCubeImplementation::addButtonFace(int pickId) switch (pickId) { default: break; - case PID_ARROW_RIGHT: - case PID_ARROW_LEFT: { + case PickId::ArrowRight: + case PickId::ArrowLeft: { pointData = { 66.6, -66.6,//outer curve 58.3, -74.0, @@ -452,10 +480,10 @@ void NaviCubeImplementation::addButtonFace(int pickId) }; break; } - case PID_ARROW_WEST: - case PID_ARROW_NORTH: - case PID_ARROW_SOUTH: - case PID_ARROW_EAST: { + case PickId::ArrowWest: + case PickId::ArrowNorth: + case PickId::ArrowSouth: + case PickId::ArrowEast: { pointData = { 100., 0., 80.,-18., @@ -463,7 +491,7 @@ void NaviCubeImplementation::addButtonFace(int pickId) }; break; } - case PID_VIEW_MENU: { + case PickId::ViewMenu: { offx = 0.84; offy = 0.84; pointData = { @@ -482,7 +510,7 @@ void NaviCubeImplementation::addButtonFace(int pickId) }; break; } - case PID_DOT_BACKSIDE: { + case PickId::DotBackside: { int steps = 16; for (int i = 0; i < steps; i++) { float angle = 2.0f * M_PI * ((float)i+0.5) / (float)steps; @@ -498,24 +526,24 @@ void NaviCubeImplementation::addButtonFace(int pickId) for (int i = 0; i < count; i++) { float x = pointData[i*2] * scale + offx; float y = pointData[i*2+1] * scale + offy; - if (pickId == PID_ARROW_NORTH || pickId == PID_ARROW_WEST || pickId == PID_ARROW_LEFT) + if (pickId == PickId::ArrowNorth || pickId == PickId::ArrowWest || pickId == PickId::ArrowLeft) x = 1.0 - x; - if (pickId == PID_ARROW_SOUTH || pickId == PID_ARROW_NORTH) + if (pickId == PickId::ArrowSouth || pickId == PickId::ArrowNorth) m_Faces[pickId].vertexArray.emplace_back(Vector3f(y, x, 0.0)); else m_Faces[pickId].vertexArray.emplace_back(Vector3f(x, y, 0.0)); } - m_Faces[pickId].type = SHAPE_BUTTON; + m_Faces[pickId].type = ShapeId::Button; } -void NaviCubeImplementation::addCubeFace( const Vector3f& x, const Vector3f& z, int shapeType, int pickId) { +void NaviCubeImplementation::addCubeFace( const Vector3f& x, const Vector3f& z, ShapeId shapeType, PickId pickId) { m_Faces[pickId].vertexArray.clear(); m_Faces[pickId].type = shapeType; Vector3f y = x.cross(-z); - if (shapeType == SHAPE_CORNER) { + if (shapeType == ShapeId::Corner) { auto xC = x * m_Chamfer; auto yC = y * m_Chamfer; auto zC = (1 - 2 * m_Chamfer) * z; @@ -527,7 +555,7 @@ void NaviCubeImplementation::addCubeFace( const Vector3f& x, const Vector3f& z, m_Faces[pickId].vertexArray.emplace_back(zC + xC + yC); m_Faces[pickId].vertexArray.emplace_back(zC - xC + yC); } - else if (shapeType == SHAPE_EDGE) { + else if (shapeType == ShapeId::Edge) { auto x4 = x * (1 - m_Chamfer * 4); auto yE = y * m_Chamfer; auto zE = z * (1 - m_Chamfer); @@ -537,7 +565,7 @@ void NaviCubeImplementation::addCubeFace( const Vector3f& x, const Vector3f& z, m_Faces[pickId].vertexArray.emplace_back(zE + x4 + yE); m_Faces[pickId].vertexArray.emplace_back(zE - x4 + yE); } - else if (shapeType == SHAPE_MAIN) { + else if (shapeType == ShapeId::Main) { auto x2 = x * (1 - m_Chamfer * 2); auto y2 = y * (1 - m_Chamfer * 2); auto x4 = x * (1 - m_Chamfer * 4); @@ -577,46 +605,46 @@ void NaviCubeImplementation::prepare() { Vector3f z(0, 0, 1); // create the main faces - addCubeFace( x, z, SHAPE_MAIN, PID_TOP); - addCubeFace( x,-y, SHAPE_MAIN, PID_FRONT); - addCubeFace(-y,-x, SHAPE_MAIN, PID_LEFT); - addCubeFace(-x, y, SHAPE_MAIN, PID_REAR); - addCubeFace( y, x, SHAPE_MAIN, PID_RIGHT); - addCubeFace( x,-z, SHAPE_MAIN, PID_BOTTOM); + addCubeFace( x, z, ShapeId::Main, PickId::Top); + addCubeFace( x,-y, ShapeId::Main, PickId::Front); + addCubeFace(-y,-x, ShapeId::Main, PickId::Left); + addCubeFace(-x, y, ShapeId::Main, PickId::Rear); + addCubeFace( y, x, ShapeId::Main, PickId::Right); + addCubeFace( x,-z, ShapeId::Main, PickId::Bottom); // add edge faces - addCubeFace(x+y, x-y+z, SHAPE_CORNER, PID_FRONT_TOP_RIGHT); - addCubeFace(x-y,-x-y+z, SHAPE_CORNER, PID_FRONT_TOP_LEFT); - addCubeFace(x+y, x-y-z, SHAPE_CORNER, PID_FRONT_BOTTOM_RIGHT); - addCubeFace(x-y,-x-y-z, SHAPE_CORNER, PID_FRONT_BOTTOM_LEFT); - addCubeFace(x-y, x+y+z, SHAPE_CORNER, PID_REAR_TOP_RIGHT); - addCubeFace(x+y,-x+y+z, SHAPE_CORNER, PID_REAR_TOP_LEFT); - addCubeFace(x-y, x+y-z, SHAPE_CORNER, PID_REAR_BOTTOM_RIGHT); - addCubeFace(x+y,-x+y-z, SHAPE_CORNER, PID_REAR_BOTTOM_LEFT); + addCubeFace(x+y, x-y+z, ShapeId::Corner, PickId::FrontTopRight); + addCubeFace(x-y,-x-y+z, ShapeId::Corner, PickId::FrontTopLeft); + addCubeFace(x+y, x-y-z, ShapeId::Corner, PickId::FrontBottomRight); + addCubeFace(x-y,-x-y-z, ShapeId::Corner, PickId::FrontBottomLeft); + addCubeFace(x-y, x+y+z, ShapeId::Corner, PickId::RearTopRight); + addCubeFace(x+y,-x+y+z, ShapeId::Corner, PickId::RearTopLeft); + addCubeFace(x-y, x+y-z, ShapeId::Corner, PickId::RearBottomRight); + addCubeFace(x+y,-x+y-z, ShapeId::Corner, PickId::RearBottomLeft); // add corner faces - addCubeFace(x, z-y, SHAPE_EDGE, PID_FRONT_TOP); - addCubeFace(x,-z-y, SHAPE_EDGE, PID_FRONT_BOTTOM); - addCubeFace(x, y-z, SHAPE_EDGE, PID_REAR_BOTTOM); - addCubeFace(x, y+z, SHAPE_EDGE, PID_REAR_TOP); - addCubeFace(z, x+y, SHAPE_EDGE, PID_REAR_RIGHT); - addCubeFace(z, x-y, SHAPE_EDGE, PID_FRONT_RIGHT); - addCubeFace(z,-x-y, SHAPE_EDGE, PID_FRONT_LEFT); - addCubeFace(z, y-x, SHAPE_EDGE, PID_REAR_LEFT); - addCubeFace(y, z-x, SHAPE_EDGE, PID_TOP_LEFT); - addCubeFace(y, x+z, SHAPE_EDGE, PID_TOP_RIGHT); - addCubeFace(y, x-z, SHAPE_EDGE, PID_BOTTOM_RIGHT); - addCubeFace(y,-z-x, SHAPE_EDGE, PID_BOTTOM_LEFT); + addCubeFace(x, z-y, ShapeId::Edge, PickId::FrontTop); + addCubeFace(x,-z-y, ShapeId::Edge, PickId::FrontBottom); + addCubeFace(x, y-z, ShapeId::Edge, PickId::RearBottom); + addCubeFace(x, y+z, ShapeId::Edge, PickId::RearTop); + addCubeFace(z, x+y, ShapeId::Edge, PickId::RearRight); + addCubeFace(z, x-y, ShapeId::Edge, PickId::FrontRight); + addCubeFace(z,-x-y, ShapeId::Edge, PickId::FrontLeft); + addCubeFace(z, y-x, ShapeId::Edge, PickId::RearLeft); + addCubeFace(y, z-x, ShapeId::Edge, PickId::TopLeft); + addCubeFace(y, x+z, ShapeId::Edge, PickId::TopRight); + addCubeFace(y, x-z, ShapeId::Edge, PickId::BottomRight); + addCubeFace(y,-z-x, ShapeId::Edge, PickId::BottomLeft); // create the flat buttons - addButtonFace(PID_ARROW_NORTH); - addButtonFace(PID_ARROW_SOUTH); - addButtonFace(PID_ARROW_EAST); - addButtonFace(PID_ARROW_WEST); - addButtonFace(PID_ARROW_LEFT); - addButtonFace(PID_ARROW_RIGHT); - addButtonFace(PID_DOT_BACKSIDE); - addButtonFace(PID_VIEW_MENU); + addButtonFace(PickId::ArrowNorth); + addButtonFace(PickId::ArrowSouth); + addButtonFace(PickId::ArrowEast); + addButtonFace(PickId::ArrowWest); + addButtonFace(PickId::ArrowLeft); + addButtonFace(PickId::ArrowRight); + addButtonFace(PickId::DotBackside); + addButtonFace(PickId::ViewMenu); if (m_PickingFramebuffer) @@ -747,7 +775,7 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) glLineWidth(m_BorderWidth*2.f); glPointSize(m_BorderWidth*2.f); float a = -1.1f; - float b = -1.0f; + float b = -1.05f; float c = 0.5f; float pointData[] = { @@ -775,11 +803,11 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); for (const auto& pair : m_Faces) { auto f = pair.second; - if (f.type == SHAPE_BUTTON) + if (f.type == ShapeId::Button) continue; auto pickId = pair.first; if (pickMode) { - glColor3ub(pickId, 0, 0); + glColor3ub(static_cast(pickId), 0, 0); } else { QColor& c = m_HiliteId == pickId ? m_HiliteColor : m_BaseColor; @@ -796,7 +824,7 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) // QColor& cb = m_EmphaseColor; for (const auto& pair : m_Faces) { auto f = pair.second; - if (f.type == SHAPE_BUTTON) + if (f.type == ShapeId::Button) continue; glColor4f(cb.redF(), cb.greenF(), cb.blueF(), cb.alphaF()); glVertexPointer(3, GL_FLOAT, 0, f.vertexArray.data()); @@ -813,7 +841,7 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); for (const auto& pair : m_LabelTextures) { auto f = pair.second; - int pickId = pair.first; + PickId pickId = pair.first; glVertexPointer(3, GL_FLOAT, 0, m_LabelTextures[pickId].vertexArray.data()); glBindTexture(GL_TEXTURE_2D, f.texture->textureId()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -832,11 +860,11 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) for (const auto& pair : m_Faces) { auto f = pair.second; - if (f.type != SHAPE_BUTTON) + if (f.type != ShapeId::Button) continue; - auto pickId = pair.first; + PickId pickId = pair.first; if (pickMode) { - glColor3ub(pickId, 0, 0); + glColor3ub(static_cast(pickId), 0, 0); } else { QColor& c = m_HiliteId == pickId ? m_HiliteColor : m_BaseColor; @@ -860,7 +888,7 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode) glPopAttrib(); } -int NaviCubeImplementation::pickFace(short x, short y) { +NaviCubeImplementation::PickId NaviCubeImplementation::pickFace(short x, short y) { GLubyte pixels[4] = {0}; if (m_PickingFramebuffer && std::abs(x) <= m_CubeWidgetSize / 2 && std::abs(y) <= m_CubeWidgetSize / 2) { @@ -879,15 +907,15 @@ int NaviCubeImplementation::pickFace(short x, short y) { GL_RGBA, GL_UNSIGNED_BYTE, &pixels); m_PickingFramebuffer->release(); } - return pixels[3] == 255 ? pixels[0] : 0; + return pixels[3] == 255 ? static_cast(pixels[0]) : PickId::None; } bool NaviCubeImplementation::mousePressed(short x, short y) { m_MouseDown = true; m_MightDrag = inDragZone(x, y); - int pick = pickFace(x, y); + PickId pick = pickFace(x, y); setHilite(pick); - return pick != 0; + return pick != PickId::None; } SbRotation NaviCubeImplementation::setView(float rotZ, float rotX) const { @@ -897,7 +925,7 @@ SbRotation NaviCubeImplementation::setView(float rotZ, float rotX) const { return rx * rz; } -SbRotation NaviCubeImplementation::rotateView(SbRotation viewRot, int axis, float rotAngle, SbVec3f customAxis) const { +SbRotation NaviCubeImplementation::rotateView(SbRotation viewRot, DirId axis, float rotAngle, SbVec3f customAxis) const { SbVec3f up; viewRot.multVec(SbVec3f(0, 1, 0), up); @@ -911,19 +939,19 @@ SbRotation NaviCubeImplementation::rotateView(SbRotation viewRot, int axis, floa switch (axis) { default: return viewRot; - case DIR_UP: + case DirId::Up: direction = up; break; - case DIR_OUT: + case DirId::Out: direction = out; break; - case DIR_RIGHT: + case DirId::Right: direction = right; break; - } - - if (customAxis != SbVec3f(0, 0, 0)) + case DirId::Custom: direction = customAxis; + break; + } SbRotation rot(direction, -rotAngle * M_PI / 180.0); SbRotation newViewRot = viewRot * rot; @@ -939,7 +967,7 @@ void NaviCubeImplementation::handleMenu() { } bool NaviCubeImplementation::mouseReleased(short x, short y) { - setHilite(0); + setHilite(PickId::None); m_MouseDown = false; // get the current view @@ -952,7 +980,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { } else { float rot = 45; float tilt = 90 - Base::toDegrees(atan(sqrt(2.0))); - int pick = pickFace(x, y); + PickId pick = pickFace(x, y); long step = Base::clamp(long(m_NaviStepByTurn), 4L, 36L); float rotStepAngle = 360.0f / step; bool applyRotation = true; @@ -963,232 +991,232 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { default: return false; break; - case PID_FRONT: + case PickId::Front: viewRot = setView(0, 90); - // we don't want to dumb rotate to the same view since depending on from where the user clicked on FRONT + // we don't want to dumb rotate to the same view since depending on from where the user clicked on Front // we have one of four suitable end positions. // we use here the same rotation logic used by other programs using OCC like "CAD Assistant" // when current matrix's 0,0 entry is larger than its |1,0| entry, we already have the final result // otherwise rotate around y if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_REAR: + case PickId::Rear: viewRot = setView(180, 90); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] > 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_LEFT: + case PickId::Left: viewRot = setView(270, 90); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] > 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][1] > 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[1][1] < 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_RIGHT: + case PickId::Right: viewRot = setView(90, 90); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] < 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][1] > 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][1] < 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_TOP: + case PickId::Top: viewRot = setView(0, 0); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_BOTTOM: + case PickId::Bottom: viewRot = setView(0, 180); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_FRONT_TOP: - // set to FRONT then rotate + case PickId::FrontTop: + // set to Front then rotate viewRot = setView(0, 90); - viewRot = rotateView(viewRot, 1, 45); + viewRot = rotateView(viewRot, DirId::Right, 45); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_FRONT_BOTTOM: - // set to FRONT then rotate + case PickId::FrontBottom: + // set to Front then rotate viewRot = setView(0, 90); - viewRot = rotateView(viewRot, 1, -45); + viewRot = rotateView(viewRot, DirId::Right, -45); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] < 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_REAR_BOTTOM: - // set to REAR then rotate + case PickId::RearBottom: + // set to Rear then rotate viewRot = setView(180, 90); - viewRot = rotateView(viewRot, 1, -45); + viewRot = rotateView(viewRot, DirId::Right, -45); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] > 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_REAR_TOP: - // set to REAR then rotate + case PickId::RearTop: + // set to Rear then rotate viewRot = setView(180, 90); - viewRot = rotateView(viewRot, 1, 45); + viewRot = rotateView(viewRot, DirId::Right, 45); if (m_RotateToNearest) { if (ViewRotMatrix[0][0] > 0 && abs(ViewRotMatrix[0][0]) >= abs(ViewRotMatrix[1][0])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][0] > 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[1][0] < 0 && abs(ViewRotMatrix[1][0]) > abs(ViewRotMatrix[0][0])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_FRONT_LEFT: - // set to FRONT then rotate + case PickId::FrontLeft: + // set to Front then rotate viewRot = setView(0, 90); - viewRot = rotateView(viewRot, 0, 45); + viewRot = rotateView(viewRot, DirId::Up, 45); if (m_RotateToNearest) { if (ViewRotMatrix[1][2] < 0 && abs(ViewRotMatrix[1][2]) >= abs(ViewRotMatrix[0][2])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[0][2] > 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[0][2] < 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_FRONT_RIGHT: - // set to FRONT then rotate + case PickId::FrontRight: + // set to Front then rotate viewRot = setView(0, 90); - viewRot = rotateView(viewRot, 0, -45); + viewRot = rotateView(viewRot, DirId::Up, -45); if (m_RotateToNearest) { if (ViewRotMatrix[1][2] < 0 && abs(ViewRotMatrix[1][2]) >= abs(ViewRotMatrix[0][2])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[0][2] > 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[0][2] < 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_REAR_RIGHT: - // set to REAR then rotate + case PickId::RearRight: + // set to Rear then rotate viewRot = setView(180, 90); - viewRot = rotateView(viewRot, 0, 45); + viewRot = rotateView(viewRot, DirId::Up, 45); if (m_RotateToNearest) { if (ViewRotMatrix[1][2] < 0 && abs(ViewRotMatrix[1][2]) >= abs(ViewRotMatrix[0][2])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[0][2] > 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[0][2] < 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_REAR_LEFT: - // set to REAR then rotate + case PickId::RearLeft: + // set to Rear then rotate viewRot = setView(180, 90); - viewRot = rotateView(viewRot, 0, -45); + viewRot = rotateView(viewRot, DirId::Up, -45); if (ViewRotMatrix[1][2] < 0 && abs(ViewRotMatrix[1][2]) >= abs(ViewRotMatrix[0][2])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[0][2] > 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[0][2] < 0 && abs(ViewRotMatrix[0][2]) > abs(ViewRotMatrix[1][2])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); break; - case PID_TOP_LEFT: - // set to LEFT then rotate + case PickId::TopLeft: + // set to Left then rotate viewRot = setView(270, 90); - viewRot = rotateView(viewRot, 1, 45); + viewRot = rotateView(viewRot, DirId::Right, 45); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] > 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][1] > 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[1][1] < 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_TOP_RIGHT: - // set to RIGHT then rotate + case PickId::TopRight: + // set to Right then rotate viewRot = setView(90, 90); - viewRot = rotateView(viewRot, 1, 45); + viewRot = rotateView(viewRot, DirId::Right, 45); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] < 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][1] > 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][1] < 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_BOTTOM_RIGHT: - // set to RIGHT then rotate + case PickId::BottomRight: + // set to Right then rotate viewRot = setView(90, 90); - viewRot = rotateView(viewRot, 1, -45); + viewRot = rotateView(viewRot, DirId::Right, -45); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] < 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][1] > 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); else if (ViewRotMatrix[1][1] < 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); } break; - case PID_BOTTOM_LEFT: - // set to LEFT then rotate + case PickId::BottomLeft: + // set to Left then rotate viewRot = setView(270, 90); - viewRot = rotateView(viewRot, 1, -45); + viewRot = rotateView(viewRot, DirId::Right, -45); if (m_RotateToNearest) { if (ViewRotMatrix[0][1] > 0 && abs(ViewRotMatrix[0][1]) >= abs(ViewRotMatrix[1][1])) - viewRot = rotateView(viewRot, 2, 180); + viewRot = rotateView(viewRot, DirId::Out, 180); else if (ViewRotMatrix[1][1] > 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, -90); + viewRot = rotateView(viewRot, DirId::Out, -90); else if (ViewRotMatrix[1][1] < 0 && abs(ViewRotMatrix[1][1]) > abs(ViewRotMatrix[0][1])) - viewRot = rotateView(viewRot, 2, 90); + viewRot = rotateView(viewRot, DirId::Out, 90); } break; - case PID_FRONT_BOTTOM_LEFT: + case PickId::FrontBottomLeft: viewRot = setView(rot - 90, 90 + tilt); // we have 3 possible end states: // - z-axis is not rotated larger than 120 deg from (0, 1, 0) -> we are already there @@ -1196,96 +1224,96 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { // - x-axis is not rotated larger than 120 deg from (0, 1, 0) if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(1, 1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(1, 1, 1)); else if (ViewRotMatrix[1][1] > 0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(1, 1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(1, 1, 1)); } break; - case PID_FRONT_BOTTOM_RIGHT: + case PickId::FrontBottomRight: viewRot = setView(90 + rot - 90, 90 + tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(-1, 1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(-1, 1, 1)); else if (ViewRotMatrix[1][1] > 0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(-1, 1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(-1, 1, 1)); } break; - case PID_REAR_BOTTOM_RIGHT: + case PickId::RearBottomRight: viewRot = setView(180 + rot - 90, 90 + tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(-1, -1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(-1, -1, 1)); else if (ViewRotMatrix[1][1] < -0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(-1, -1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(-1, -1, 1)); } break; - case PID_REAR_BOTTOM_LEFT: + case PickId::RearBottomLeft: viewRot = setView(270 + rot - 90, 90 + tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(1, -1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(1, -1, 1)); else if (ViewRotMatrix[1][1] < -0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(1, -1, 1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(1, -1, 1)); } break; - case PID_FRONT_TOP_RIGHT: + case PickId::FrontTopRight: viewRot = setView(rot, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(-1, 1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(-1, 1, -1)); else if (ViewRotMatrix[1][1] < -0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(-1, 1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(-1, 1, -1)); } break; - case PID_FRONT_TOP_LEFT: + case PickId::FrontTopLeft: viewRot = setView(rot - 90, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(1, 1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(1, 1, -1)); else if (ViewRotMatrix[1][1] < -0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(1, 1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(1, 1, -1)); } break; - case PID_REAR_TOP_LEFT: + case PickId::RearTopLeft: viewRot = setView(rot - 180, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] < -0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(1, -1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(1, -1, -1)); else if (ViewRotMatrix[1][1] > 0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(1, -1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(1, -1, -1)); } break; - case PID_REAR_TOP_RIGHT: + case PickId::RearTopRight: viewRot = setView(rot - 270, 90 - tilt); if (m_RotateToNearest) { if (ViewRotMatrix[1][0] > 0.4823) - viewRot = rotateView(viewRot, 0, 120, SbVec3f(-1, -1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, 120, SbVec3f(-1, -1, -1)); else if (ViewRotMatrix[1][1] > 0.4823) - viewRot = rotateView(viewRot, 0, -120, SbVec3f(-1, -1, -1)); + viewRot = rotateView(viewRot, DirId::Custom, -120, SbVec3f(-1, -1, -1)); } break; - case PID_ARROW_LEFT: - viewRot = rotateView(viewRot, DIR_OUT, rotStepAngle); + case PickId::ArrowLeft: + viewRot = rotateView(viewRot, DirId::Out, rotStepAngle); break; - case PID_ARROW_RIGHT: - viewRot = rotateView(viewRot, DIR_OUT, -rotStepAngle); + case PickId::ArrowRight: + viewRot = rotateView(viewRot, DirId::Out, -rotStepAngle); break; - case PID_ARROW_WEST: - viewRot = rotateView(viewRot, DIR_UP, -rotStepAngle); + case PickId::ArrowWest: + viewRot = rotateView(viewRot, DirId::Up, -rotStepAngle); break; - case PID_ARROW_EAST: - viewRot = rotateView(viewRot, DIR_UP, rotStepAngle); + case PickId::ArrowEast: + viewRot = rotateView(viewRot, DirId::Up, rotStepAngle); break; - case PID_ARROW_NORTH: - viewRot = rotateView(viewRot, DIR_RIGHT, -rotStepAngle); + case PickId::ArrowNorth: + viewRot = rotateView(viewRot, DirId::Right, -rotStepAngle); break; - case PID_ARROW_SOUTH: - viewRot = rotateView(viewRot, DIR_RIGHT, rotStepAngle); + case PickId::ArrowSouth: + viewRot = rotateView(viewRot, DirId::Right, rotStepAngle); break; - case PID_DOT_BACKSIDE: - viewRot = rotateView(viewRot, DIR_UP, 180); + case PickId::DotBackside: + viewRot = rotateView(viewRot, DirId::Up, 180); break; - case PID_VIEW_MENU: + case PickId::ViewMenu: handleMenu(); applyRotation = false; break; @@ -1297,7 +1325,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) { return true; } -void NaviCubeImplementation::setHilite(int hilite) { +void NaviCubeImplementation::setHilite(PickId hilite) { if (hilite != m_HiliteId) { m_HiliteId = hilite; m_View3DInventorViewer->getSoRenderManager()->scheduleRedraw(); @@ -1316,7 +1344,7 @@ bool NaviCubeImplementation::mouseMoved(short x, short y) { if (m_MouseDown && m_Draggable) { if (m_MightDrag && !m_Dragging) { m_Dragging = true; - setHilite(0); + setHilite(PickId::None); } if (m_Dragging && (std::abs(x) || std::abs(y))) { float newX = m_RelPos[0] + (float)(x) / m_PosAreaSize[0]; diff --git a/src/Gui/NaviCube.h b/src/Gui/NaviCube.h index c18701c639..0384b63c17 100644 --- a/src/Gui/NaviCube.h +++ b/src/Gui/NaviCube.h @@ -65,7 +65,7 @@ public: void setHiliteColor(QColor HiliteColor); void setBorderWidth(double BorderWidth); void setShowCS(bool showCS); - // front, top, right, rear, bottom, left + // Label order: front, top, right, rear, bottom, left void setNaviCubeLabels(const std::vector& labels); static void setNaviCubeCommands(const std::vector& cmd);