diff --git a/avogadro/CMakeLists.txt b/avogadro/CMakeLists.txt index 6c79b569..89acc266 100644 --- a/avogadro/CMakeLists.txt +++ b/avogadro/CMakeLists.txt @@ -162,6 +162,15 @@ elseif(WIN32) list(APPEND avogadro_srcs icons/avogadro.rc) endif() +if(USE_3DCONNEXION AND (WIN32 OR APPLE)) + list(APPEND avogadro_srcs icons/3dx_pivot.png) + list(APPEND avogadro_srcs tdxcontroller.cpp) + list(APPEND avogadro_srcs "${AvogadroApp_SOURCE_DIR}/thirdparty/3DConnexion/src/navlib_load.cpp") + list(APPEND avogadro_srcs "${AvogadroApp_SOURCE_DIR}/thirdparty/3DConnexion/src/navlib_stub.c") + set_source_files_properties(icons/3dx_pivot.png PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) +endif() + add_executable(avogadro WIN32 MACOSX_BUNDLE ${avogadro_srcs} ${ui_srcs} ${rcc_srcs}) target_link_libraries(avogadro Qt::Widgets Qt::Network Qt::Concurrent) @@ -188,6 +197,18 @@ endif() if(QT_VERSION EQUAL 6) target_link_libraries(avogadro Qt6::Core5Compat) endif() + +if(USE_3DCONNEXION AND (WIN32 OR APPLE)) + target_compile_definitions(avogadro PUBLIC _3DCONNEXION) + target_include_directories(avogadro PUBLIC "${AvogadroApp_SOURCE_DIR}/thirdparty/3DConnexion/inc") + if(APPLE) + target_compile_definitions(avogadro PUBLIC __APPLE__) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdeclspec") + elseif(WIN32) + install(FILES "icons/3dx_pivot.png" DESTINATION "${CMAKE_INSTALL_BINDIR}/img") + endif() +endif() + install(TARGETS avogadro RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} BUNDLE DESTINATION . diff --git a/avogadro/icons/3dx_pivot.png b/avogadro/icons/3dx_pivot.png new file mode 100644 index 00000000..98525adc Binary files /dev/null and b/avogadro/icons/3dx_pivot.png differ diff --git a/avogadro/mainwindow.cpp b/avogadro/mainwindow.cpp index cc54ee19..db36be55 100644 --- a/avogadro/mainwindow.cpp +++ b/avogadro/mainwindow.cpp @@ -12,6 +12,7 @@ #include "renderingdialog.h" #include "tooltipfilter.h" #include "viewfactory.h" +#include "tdxcontroller.h" #include #include @@ -245,6 +246,9 @@ MainWindow::MainWindow(const QStringList& fileNames, bool disableSettings) , m_redo(nullptr) , m_copyImage(nullptr) , m_viewFactory(new ViewFactory) +#ifdef _3DCONNEXION + , m_TDxController(nullptr) +#endif { // If disable settings, ensure we create a cleared QSettings object. if (disableSettings) { @@ -312,10 +316,35 @@ MainWindow::MainWindow(const QStringList& fileNames, bool disableSettings) statusBar()->showMessage(tr("Ready…"), 2000); updateWindowTitle(); + +#ifdef _3DCONNEXION + GLWidget* glWidget = + qobject_cast(m_multiViewWidget->activeWidget()); + + m_TDxController = new TDxController(this, glWidget); + + connect(this, &MainWindow::moleculeChanged, m_TDxController, + &TDxController::updateMolecule); + + m_TDxController->enableController(); + + QMap> actionsMap = m_menuBuilder->getMenuActions(); + QList toolActions; + + for (auto tool : m_tools) + toolActions.push_back(tool->activateAction()); + + actionsMap.insert("Toolbox", toolActions); + + m_TDxController->exportCommands(actionsMap); +#endif } MainWindow::~MainWindow() { +#ifdef _3DCONNEXION + m_TDxController->disableController(); +#endif writeSettings(); delete m_molecule; delete m_menuBuilder; @@ -1810,7 +1839,7 @@ void MainWindow::buildMenu() m_menuBuilder->addAction(path, action, 960); m_fileToolBar->addAction(action); connect(action, SIGNAL(triggered()), SLOT(saveFileAs())); - + // Export QStringList exportPath = path; exportPath << tr("&Export"); diff --git a/avogadro/mainwindow.h b/avogadro/mainwindow.h index afca6650..906a8d28 100644 --- a/avogadro/mainwindow.h +++ b/avogadro/mainwindow.h @@ -33,7 +33,7 @@ namespace QtOpenGL { class GLWidget; } -namespace Io { +namespace Io { class FileFormat; } @@ -48,6 +48,9 @@ class RWMolecule; class LayerModel; } +#ifdef _3DCONNEXION +class TDxController; +#endif /** * @class MainWindow * @author Marcus D. Hanwell @@ -404,6 +407,9 @@ private slots: ViewFactory* m_viewFactory; QNetworkAccessManager* m_network = nullptr; +#ifdef _3DCONNEXION + TDxController* m_TDxController; +#endif #ifdef QTTESTING pqTestUtility* m_testUtility; diff --git a/avogadro/menubuilder.h b/avogadro/menubuilder.h index ddb306f3..349dc0a8 100644 --- a/avogadro/menubuilder.h +++ b/avogadro/menubuilder.h @@ -62,6 +62,14 @@ class MenuBuilder : public QObject */ void print(); + /** + * @brief Get the map of string to action lists. + */ + const QMap>& getMenuActions() const + { + return m_menuActions; + }; + private: /** A map of string to action lists. */ QMap> m_menuActions; diff --git a/avogadro/tdxcontroller.cpp b/avogadro/tdxcontroller.cpp new file mode 100644 index 00000000..1d7c6f25 --- /dev/null +++ b/avogadro/tdxcontroller.cpp @@ -0,0 +1,570 @@ +/****************************************************************************** + This source file is part of the Avogadro project. + This source code is released under the 3-Clause BSD License, (see "LICENSE"). +******************************************************************************/ + +#include "tdxcontroller.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include > + +#include + +Avogadro::TDxController::TDxController( + MainWindow* const mainWindow, Avogadro::QtOpenGL::GLWidget* const pGLWidget) + : CNavigation3D(false, true) + , QObject(mainWindow) + , m_pRootNode(std::make_shared("User Interface")) + , m_pGLWidget(pGLWidget) + , m_pMolecule(mainWindow->molecule()) + , m_pGLRenderer(&pGLWidget->renderer()) + , m_eyePosition({ 0.0, 0.0, 0.0 }) + , m_lookDirection({ 0.0, 0.0, 0.0 }) + , m_hitTestRadius(0.0) +{ + if (rayCount > 0) { + m_rayOrigins[0].x = 0.0; + m_rayOrigins[0].y = 0.0; + } + + for (uint32_t i = 1; i < rayCount; i++) { + float coefficient = + sqrt(static_cast(i) / static_cast(rayCount)); + float angle = 2.4f * static_cast(i); + float x = coefficient * sin(angle); + float y = coefficient * cos(angle); + m_rayOrigins[i].x = x; + m_rayOrigins[i].y = y; + } + + QString pivotImagePath = QCoreApplication::applicationDirPath(); + +#ifdef WIN32 + pivotImagePath.append("/img/3dx_pivot.png"); +#else + pivotImagePath.append("/../Resources/3dx_pivot.png"); +#endif + + m_pivotImage = QImage(pivotImagePath); + + if (!m_pivotImage.isNull() && m_pGLRenderer != nullptr) { + m_pGLRenderer->m_iconData = reinterpret_cast(m_pivotImage.bits()); + m_pGLRenderer->m_iconWidth = m_pivotImage.width(); + m_pGLRenderer->m_iconHeight = m_pivotImage.height(); + } +} + +void Avogadro::TDxController::enableController() +{ + PutProfileHint("Avogadro2"); + + EnableNavigation(true, errorCode); + + if (errorCode) + return; + + PutFrameTimingSource(TimingSource::SpaceMouse); + + return; +} + +void Avogadro::TDxController::exportCommands( + const QMap>& actionsMap) +{ + if (errorCode) + return; + + TDx::SpaceMouse::CCommandSet commandSet("Default", "Main"); + + for (auto& key : actionsMap.keys()) + addActions(key.toStdString(), m_pRootNode, actionsMap[key]); + + std::string pathCode; + + for (uint32_t i = 0; i < m_pRootNode->m_children.size(); i++) { + pathCode.append(std::to_string(i)); + pathCode.append("."); + commandSet.push_back(getCategory(pathCode, m_pRootNode->m_children[i])); + pathCode.clear(); + } + + AddCommandSet(commandSet); + PutActiveCommands("Default"); + +#ifdef WIN32 + AddImages(m_utilityIcons); +#endif +} + +void Avogadro::TDxController::updateMolecule(QtGui::Molecule* const pMolecule) +{ + if (pMolecule == nullptr) + return; + + m_pMolecule = pMolecule; + + navlib::box_t modelExtents; + + GetModelExtents(modelExtents); + Write(navlib::model_extents_k, modelExtents); +} + +void Avogadro::TDxController::disableController() +{ + EnableNavigation(false, errorCode); + return; +} + +void Avogadro::TDxController::addActions( + const std::string& path, const std::shared_ptr& pNode, + const QList& actions) +{ + + if (path.empty()) { + std::copy(actions.begin(), actions.end(), + std::back_inserter(pNode->m_actions)); + return; + } + + std::string childName; + std::string remainingPath; + + for (auto itr = path.begin(); itr != path.end(); itr++) { + if (*itr != '&' && *itr != '|') + childName.push_back(*itr); + + if (*itr == '|') { + std::copy(itr + 1, path.end(), std::back_inserter(remainingPath)); + break; + } + } + + for (auto& pNode : pNode->m_children) { + if (pNode->m_nodeName == childName) { + addActions(remainingPath, pNode, actions); + return; + } + } + + auto pNewChild = std::make_shared(childName); + pNode->m_children.push_back(pNewChild); + + addActions(remainingPath, pNewChild, actions); + + return; +} + +QAction* Avogadro::TDxController::decodeAction( + const std::string& pathCode, + const std::shared_ptr& pNode) const +{ + std::string indexString; + std::string remainingPath; + + for (auto itr = pathCode.begin(); itr != pathCode.end(); itr++) { + if (*itr != '.') { + indexString.push_back(*itr); + } else { + std::copy(itr + 1, pathCode.end(), std::back_inserter(remainingPath)); + break; + } + } + + int32_t index = std::stoi(indexString); + + if (index < 0) + return nullptr; + + if (remainingPath.empty()) { + if (index >= pNode->m_actions.size()) + return nullptr; + return pNode->m_actions[index]; + } + + if (index >= pNode->m_children.size()) + return nullptr; + + return decodeAction(remainingPath, pNode->m_children[index]); +} + +// Inherited via CNavigation3D +// Getters + +long Avogadro::TDxController::GetCameraMatrix(navlib::matrix_t& matrix) const +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + Eigen::Matrix4f _cameraMatrix = + m_pGLRenderer->camera().modelView().matrix().inverse(); + + matrix.m00 = _cameraMatrix(0, 0); + matrix.m10 = _cameraMatrix(1, 0); + matrix.m20 = _cameraMatrix(2, 0); + matrix.m30 = _cameraMatrix(3, 0); + + matrix.m01 = _cameraMatrix(0, 1); + matrix.m11 = _cameraMatrix(1, 1); + matrix.m21 = _cameraMatrix(2, 1); + matrix.m31 = _cameraMatrix(3, 1); + + matrix.m02 = _cameraMatrix(0, 2); + matrix.m12 = _cameraMatrix(1, 2); + matrix.m22 = _cameraMatrix(2, 2); + matrix.m32 = _cameraMatrix(3, 2); + + matrix.m03 = _cameraMatrix(0, 3); + matrix.m13 = _cameraMatrix(1, 3); + matrix.m23 = _cameraMatrix(2, 3); + matrix.m33 = _cameraMatrix(3, 3); + + return 0; +} + +long Avogadro::TDxController::GetPointerPosition( + navlib::point_t& position) const +{ + if (m_pGLRenderer == nullptr || m_pGLWidget == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + QPoint pointerPos = m_pGLWidget->cursor().pos(); + pointerPos = m_pGLWidget->mapFromGlobal(pointerPos); + + Eigen::Vector3f worldPos = m_pGLRenderer->camera().unProject( + Eigen::Vector2f(pointerPos.x(), pointerPos.y())); + + position.x = worldPos.x(); + position.y = worldPos.y(); + position.z = worldPos.z(); + + return 0; +} + +long Avogadro::TDxController::GetViewExtents(navlib::box_t& extents) const +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + extents.min.x = m_pGLRenderer->m_orthographicFrustum[0]; + extents.min.y = m_pGLRenderer->m_orthographicFrustum[2]; + extents.min.z = -m_pGLRenderer->m_orthographicFrustum[5]; + extents.max.x = m_pGLRenderer->m_orthographicFrustum[1]; + extents.max.y = m_pGLRenderer->m_orthographicFrustum[3]; + extents.max.z = -m_pGLRenderer->m_orthographicFrustum[4]; + return 0; +} + +long Avogadro::TDxController::GetViewFOV(double& fov) const +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::GetViewFrustum(navlib::frustum_t& frustum) const +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + frustum.left = m_pGLRenderer->m_perspectiveFrustum[0]; + frustum.right = m_pGLRenderer->m_perspectiveFrustum[1]; + frustum.bottom = m_pGLRenderer->m_perspectiveFrustum[2]; + frustum.top = m_pGLRenderer->m_perspectiveFrustum[3]; + frustum.nearVal = m_pGLRenderer->m_perspectiveFrustum[4]; + frustum.farVal = m_pGLRenderer->m_perspectiveFrustum[5]; + return 0; +} + +long Avogadro::TDxController::GetIsViewPerspective( + navlib::bool_t& perspective) const +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + perspective = (m_pGLRenderer->camera().projectionType() == + Avogadro::Rendering::Projection::Perspective); + return 0; +} + +TDx::SpaceMouse::CCategory Avogadro::TDxController::getCategory( + const std::string& pathCode, const std::shared_ptr& pNode) +{ + + TDx::SpaceMouse::CCategory result(pNode->m_nodeName, pNode->m_nodeName); + std::string nextPathCode(pathCode); + + for (uint32_t i = 0u; i < pNode->m_children.size(); i++) { + nextPathCode.append(std::to_string(i)); + nextPathCode.push_back('.'); + result.push_back(getCategory(nextPathCode, pNode->m_children[i])); + nextPathCode = pathCode; + } + + for (uint32_t i = 0u; i < pNode->m_actions.size(); i++) { + + if (pNode->m_actions[i]->iconText().isEmpty()) + continue; + + std::string commandId(nextPathCode + std::to_string(i)); + + result.push_back(TDx::SpaceMouse::CCommand( + commandId, pNode->m_actions[i]->iconText().toStdString(), + pNode->m_actions[i]->toolTip().toStdString())); + +#ifdef WIN32 + + const QIcon iconImg = pNode->m_actions[i]->icon(); + const QImage qimage = iconImg.pixmap(QSize(256, 256)).toImage(); + QByteArray qbyteArray; + QBuffer qbuffer(&qbyteArray); + qimage.save(&qbuffer, "PNG"); + + TDx::CImage icon = + TDx::CImage::FromData(qbyteArray.toStdString(), 0, commandId.c_str()); + + m_utilityIcons.push_back(icon); +#endif + } + return result; +} + +long Avogadro::TDxController::GetModelExtents(navlib::box_t& extents) const +{ + if (m_pMolecule == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + Vector3 boxMin; + Vector3 boxMax; + + m_pMolecule->boundingBox(boxMin, boxMax); + + std::copy_n(boxMin.data(), 3u, &extents.min.x); + std::copy_n(boxMax.data(), 3u, &extents.max.x); + + return 0; +} + +long Avogadro::TDxController::GetSelectionExtents(navlib::box_t& extents) const +{ + return GetModelExtents(extents); +} + +long Avogadro::TDxController::GetSelectionTransform( + navlib::matrix_t& transform) const +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::GetIsSelectionEmpty(navlib::bool_t& empty) const +{ + if (m_pMolecule == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + empty = m_pMolecule->isSelectionEmpty(); + + return 0; +} + +long Avogadro::TDxController::GetPivotPosition(navlib::point_t& position) const +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::GetPivotVisible(navlib::bool_t& visible) const +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + visible = m_pGLRenderer->m_drawIcon; + return 0; +} + +long Avogadro::TDxController::GetHitLookAt(navlib::point_t& position) const +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + constexpr float divThreshold = 0.01f; + const float rayLength = + 2.0f * m_pGLRenderer->camera().distance(m_pGLRenderer->scene().center()) + + m_pGLRenderer->scene().radius(); + const Eigen::Matrix4f transform = + m_pGLRenderer->camera().modelView().matrix().inverse(); + Eigen::Vector4f origin = Eigen::Vector4f::Zero(); + float distance = std::numeric_limits::max(); + + if (m_hitTestRadius < divThreshold) { + origin = transform * Eigen::Vector4f(0., 0., 0., 1.); + origin /= origin.w(); + + auto rayOrigin = Eigen::Vector3f(origin.x(), origin.y(), origin.z()); + auto rayDirection = + Eigen::Vector3f(m_lookDirection.x, m_lookDirection.y, m_lookDirection.z); + + distance = m_pGLRenderer->hit( + rayOrigin, rayOrigin + rayLength * rayDirection, rayDirection); + + } else { + + Eigen::Vector4f originBuffer = Eigen::Vector4f::Zero(); + + for (uint32_t i = 0; i < rayCount; i++) { + + float x = m_hitTestRadius * m_rayOrigins[i].x; + float y = m_hitTestRadius * m_rayOrigins[i].y; + + originBuffer = transform * Eigen::Vector4f(x, y, 0., 1.); + originBuffer /= originBuffer.w(); + + auto rayOrigin = + Eigen::Vector3f(originBuffer.x(), originBuffer.y(), originBuffer.z()); + auto rayDirection = Eigen::Vector3f(m_lookDirection.x, m_lookDirection.y, + m_lookDirection.z); + + float buffer = m_pGLRenderer->hit( + rayOrigin, rayOrigin + rayLength * rayDirection, rayDirection); + + if (buffer > 0.0f && buffer < distance) { + origin = originBuffer; + distance = buffer; + } + } + } + + if (distance != std::numeric_limits::max()) { + position.x = origin.x() + distance * m_lookDirection.x; + position.y = origin.y() + distance * m_lookDirection.y; + position.z = origin.z() + distance * m_lookDirection.z; + return 0; + } else + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +// Setters + +long Avogadro::TDxController::SetCameraMatrix(const navlib::matrix_t& matrix) +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + Avogadro::Vector3f from(matrix.m03, matrix.m13, matrix.m23); + Avogadro::Vector3f to = + from - Avogadro::Vector3f(matrix.m02, matrix.m12, matrix.m22); + Avogadro::Vector3f up(matrix.m01, matrix.m11, matrix.m21); + + m_pGLRenderer->camera().lookAt(from, to, up); + + return 0; +} + +long Avogadro::TDxController::SetViewExtents(const navlib::box_t& extents) +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + m_pGLRenderer->m_orthographicFrustum[0] = extents.min.x; + m_pGLRenderer->m_orthographicFrustum[1] = extents.max.x; + m_pGLRenderer->m_orthographicFrustum[2] = extents.min.y; + m_pGLRenderer->m_orthographicFrustum[3] = extents.max.y; + m_pGLRenderer->m_orthographicFrustum[4] = -extents.max.z; + m_pGLRenderer->m_orthographicFrustum[5] = -extents.min.z; + + return 0; +} + +long Avogadro::TDxController::SetViewFOV(double fov) +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::SetViewFrustum(const navlib::frustum_t& frustum) +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::SetSelectionTransform( + const navlib::matrix_t& matrix) +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::IsUserPivot(navlib::bool_t& userPivot) const +{ + userPivot = false; + return 0; +} + +long Avogadro::TDxController::SetPivotPosition(const navlib::point_t& position) +{ + if (m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + m_pGLRenderer->m_iconPosition.x() = position.x; + m_pGLRenderer->m_iconPosition.y() = position.y; + m_pGLRenderer->m_iconPosition.z() = position.z; + return 0; +} + +long Avogadro::TDxController::SetPivotVisible(bool visible) +{ + if (m_pGLWidget == nullptr || m_pGLRenderer == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + m_pGLRenderer->m_drawIcon = visible; + m_pGLWidget->requestUpdate(); + return 0; +} + +long Avogadro::TDxController::SetHitAperture(double aperture) +{ + m_hitTestRadius = aperture / 2.0; + return 0; +} + +long Avogadro::TDxController::SetHitDirection(const navlib::vector_t& direction) +{ + m_lookDirection = direction; + return 0; +} + +long Avogadro::TDxController::SetHitLookFrom(const navlib::point_t& eye) +{ + m_eyePosition = eye; + return 0; +} + +long Avogadro::TDxController::SetHitSelectionOnly(bool onlySelection) +{ + return navlib::make_result_code(navlib::navlib_errc::no_data_available); +} + +long Avogadro::TDxController::SetActiveCommand(std::string commandId) +{ + QAction* pDecodedAction = decodeAction(commandId, m_pRootNode); + + if (pDecodedAction == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + pDecodedAction->trigger(); + + return 0; +} + +long Avogadro::TDxController::SetTransaction(long value) +{ + if (m_pGLWidget == nullptr) + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + + m_pGLWidget->requestUpdate(); + + return 0; +} diff --git a/avogadro/tdxcontroller.h b/avogadro/tdxcontroller.h new file mode 100644 index 00000000..41cc583f --- /dev/null +++ b/avogadro/tdxcontroller.h @@ -0,0 +1,163 @@ +/****************************************************************************** + This source file is part of the Avogadro project. + This source code is released under the 3-Clause BSD License, (see "LICENSE"). +******************************************************************************/ + +#ifdef _3DCONNEXION +#ifndef AVOGADRO_TDXCONTROLLER_H +#define AVOGADRO_TDXCONTROLLER_H + +#include +#include + +#include "mainwindow.h" +#include +#include +#include +#include +#include + +constexpr uint32_t rayCount = 50; + +class QAction; + +namespace Avogadro { + +namespace Rendering { +class Camera; +class GLRenderer; +} + +namespace QtOpenGL { +class GLWidget; +} + +namespace QtGui { +class Molecule; +class ToolPlugin; +} + +/** + * This class is responsible for handling the TDx navigation in Avogadro2. + */ +class TDxController + : private TDx::SpaceMouse::Navigation3D::CNavigation3D + , public QObject +{ +public: + TDxController(MainWindow* const mainWindow, + Avogadro::QtOpenGL::GLWidget* const pGLWidget); + /** + * Enables the TDx navigation. + */ + void enableController(); + + /** + * Disables the TDx navigation. + */ + void disableController(); + + /** + * Exports interface utilities to the TDx wizard. + * @param &actionsMap A map that contains pairs which constists of a string + * and an action list. The string represents a path through UI menus and + * submenus, to reach corresponding actions. Submenus names are expected + * to be separated by '|' char. + */ + void exportCommands(const QMap>& actionsMap); + + void updateMolecule(QtGui::Molecule* const pMolecule); + +private: + struct ActionTreeNode + { + std::string m_nodeName; + std::vector> m_children; + std::vector m_actions; + explicit ActionTreeNode(const std::string& nodeName) + : m_nodeName(nodeName) + { + } + }; + std::shared_ptr m_pRootNode; + QtOpenGL::GLWidget* m_pGLWidget; + Rendering::GLRenderer* m_pGLRenderer; + QtGui::Molecule* m_pMolecule; + navlib::point_t m_eyePosition; + navlib::vector_t m_lookDirection; + QImage m_pivotImage; +#ifdef WIN32 + std::vector m_utilityIcons; +#endif + double m_hitTestRadius; + std::array m_rayOrigins; + std::error_code errorCode; + + /** + * Adds a actions list to the action tree. + * @param &path describes the recursive traversal through tree nodes + * to the destination node. Nodes that does not exist will be created. + * @param &pNode traversal starting point + * @param &actions action list to add to the tree node + */ + void addActions(const std::string& path, + const std::shared_ptr& pNode, + const QList& actions); + + /** + * Returns CCategory hierarchy which reflects the actions tree. + * Created CCommand's ID's are encoded paths to the actions in the tree. + * @param &pNode root of the action tree + */ + TDx::SpaceMouse::CCategory getCategory( + const std::string& pathCode, const std::shared_ptr& pNode); + + /** + * Recursively decodes a path from provided code and returns a QAction pointer + * that has been reached in the actions tree. If the code is invalid, then + * nullptr is returned. + * @param &pathCode encoded path to the action in the actions tree + * @param &pNode node from which the decoding begins + */ + QAction* decodeAction(const std::string& pathCode, + const std::shared_ptr& pNode) const; + + // Inherited via CNavigation3D + // Getters + + virtual long GetCameraMatrix(navlib::matrix_t& matrix) const override; + virtual long GetPointerPosition(navlib::point_t& position) const override; + virtual long GetViewExtents(navlib::box_t& extents) const override; + virtual long GetViewFOV(double& fov) const override; + virtual long GetViewFrustum(navlib::frustum_t& frustum) const override; + virtual long GetIsViewPerspective(navlib::bool_t& perspective) const override; + virtual long GetModelExtents(navlib::box_t& extents) const override; + virtual long GetSelectionExtents(navlib::box_t& extents) const override; + virtual long GetSelectionTransform( + navlib::matrix_t& transform) const override; + virtual long GetIsSelectionEmpty(navlib::bool_t& empty) const override; + virtual long GetPivotPosition(navlib::point_t& position) const override; + virtual long GetPivotVisible(navlib::bool_t& visible) const override; + virtual long GetHitLookAt(navlib::point_t& position) const override; + + // Setters + + virtual long SetCameraMatrix(const navlib::matrix_t& matrix) override; + virtual long SetViewExtents(const navlib::box_t& extents) override; + virtual long SetViewFOV(double fov) override; + virtual long SetViewFrustum(const navlib::frustum_t& frustum) override; + virtual long SetSelectionTransform(const navlib::matrix_t& matrix) override; + virtual long IsUserPivot(navlib::bool_t& userPivot) const override; + virtual long SetPivotPosition(const navlib::point_t& position) override; + virtual long SetPivotVisible(bool visible) override; + virtual long SetHitAperture(double aperture) override; + virtual long SetHitDirection(const navlib::vector_t& direction) override; + virtual long SetHitLookFrom(const navlib::point_t& eye) override; + virtual long SetHitSelectionOnly(bool onlySelection) override; + virtual long SetActiveCommand(std::string commandId) override; + virtual long SetTransaction(long value) override; +}; +} + +#endif // ! AVOGADRO_TDXCONTROLLER_H +#endif // _3DCONNEXION \ No newline at end of file diff --git a/thirdparty/3DConnexion/README.txt b/thirdparty/3DConnexion/README.txt new file mode 100644 index 00000000..894bd0bc --- /dev/null +++ b/thirdparty/3DConnexion/README.txt @@ -0,0 +1,3 @@ +This directory contains part of the the 3Dconnexion 3DxWare_SDK v4 +The full sdk can be obtained from https://3dconnexion.com/software-developer-program/ + diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CActionInput.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CActionInput.hpp new file mode 100644 index 00000000..1b3f2819 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CActionInput.hpp @@ -0,0 +1,336 @@ +#ifndef CInputAction_HPP_INCLUDED +#define CInputAction_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CNavigation3D.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// + +// SpaceMouse +#include +#include +#include +#include +#include +#include + +// stdlib +#include +#include +#include + +// navlib +#include +#include + +namespace TDx { +namespace SpaceMouse { +/// +/// Contains types that support 3Dconnexion SpaceMouse input action interface. +/// +namespace ActionInput { +/// +/// The base class for 3D navigation implements defaults for the interface. +/// +/// This class can be used as the base class for the application specific implementation of +/// the accessors. +class CActionInput : public Navigation3D::INavlibProperty, protected IActionAccessors { +public: + /// + /// Initializes a new instance of the class. + /// + /// Allow multithreading. + /// Set multithreaded to true for a windows console application. If the application + /// requires that the callbacks are executed on the main thread, either leave as false, or marshall + /// the callbacks back to the main thread. + CActionInput(bool multiThreaded = false) + : m_enabled(false), m_pImpl(CActionInputImpl::CreateInstance(this, multiThreaded)) { + } + +#if defined(_MSC_EXTENSIONS) + /// + /// Gets or sets a value indicating whether the connection to the input device is enabled. + /// + __declspec(property(get = IsEnabled, put = PutEnable)) bool Enable; + + /// + /// Gets or sets the text to pass to the 3Dconnexion driver to use in Properties Utility. + /// + /// If the connection to the navlib is already open, the connection is closed and + /// reopened. + __declspec(property(get = GetProfileHint, put = PutProfileHint)) std::string Profile; + + /// + /// Gets or sets a value representing the active command set. + /// + /// + __declspec(property(get = GetActiveCommands, put = PutActiveCommands)) std::string ActiveCommands; + +#endif + + /// + /// Gets a value indicating whether action interface is enabled. + /// + /// true if enabled, otherwise false. + bool IsEnabled() const { + return m_enabled; + } + + /// + /// Sets a value indicating whether the action interface is enabled. + /// + /// true to enable, false to disable. + /// The text for the '3Dconnexion Properties' is + /// empty. + /// Cannot create a connection to the library. + void PutEnable(bool value) { + if (m_enabled == value) { + return; + } + if (value) { + m_pImpl->Open(m_profileHint); + m_enabled = true; + } else { + m_pImpl->Close(); + m_enabled = false; + } + } + + /// + /// Sets a value indicating whether the action interface is enabled. + /// + /// true to enable, false to disable. + /// The contains the error if something goes + /// wrong. + /// The text for the '3Dconnexion Properties' is + /// empty. + /// Cannot create a connection to the library. + void PutEnable(bool value, std::error_code &ec) NOEXCEPT { + try { + PutEnable(value); + } +#if defined(_DEBUG) && defined(TRACE_NAVLIB) + catch (const std::system_error &e) { + ec = e.code(); + std::cerr << "system_error exception thrown in EnableNavigation(" << value << ") 0x" + << std::hex << ec.value() << std::dec << ", " << ec.message() << ", " << e.what() + << "\n"; + } catch (const std::invalid_argument &e) { + ec = std::make_error_code(std::errc::invalid_argument); + std::cerr << "invalid_argument exception thrown in EnableNavigation(" << value << ") 0x" + << std::hex << ec.value() << std::dec << ", " << ec.message() << ", " << e.what() + << "\n"; + } catch (const std::exception &e) { + ec = std::make_error_code(std::errc::io_error); + std::cerr << "exception thrown in EnableNavigation(" << value << ") 0x" << std::hex + << ec.value() << std::dec << ", " << ec.message() << ", " << e.what() << "\n"; + } +#else + catch (const std::system_error &e) { + ec = e.code(); + } catch (const std::invalid_argument &) { + ec = std::make_error_code(std::errc::invalid_argument); + } catch (const std::exception &) { + ec = std::make_error_code(std::errc::io_error); + } +#endif + } + + /// + /// Gets or sets the text to pass to the 3Dconnexion driver to use in Properties Utility. + /// + /// If the connection to the navlib is already open, the connection is closed and + /// reopened. + std::string GetProfileHint() const { + return m_profileHint; + } + void PutProfileHint(std::string const &value) { + if (m_profileHint != value) { + m_profileHint = value; + if (IsEnabled()) { + PutEnable(false); + PutEnable(true); + } + } + } + + /// + /// Gets or sets a value representing the active command set. + /// + /// + std::string GetActiveCommands() const { + std::string result; + long error = m_pImpl->Read(navlib::commands_activeSet_k, result); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + return result; + } + void PutActiveCommands(const std::string &id) { + long error = m_pImpl->Write(navlib::commands_activeSet_k, id); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Add commands to the sets of commands. + /// + /// The to add. + /// + void AddCommands(const CCommandTree &commands) { + const SiActionNodeEx_t *pnode = &commands.GetSiActionNode(); + long error = m_pImpl->Write(navlib::commands_tree_k, pnode); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Add a set of commands to the sets of commands. + /// + /// The to add. + /// + void AddCommandSet(const CCommandSet &commands) { + AddCommands(commands); + } + + /// + /// Add to the images available to the 3Dconnexion properties utility. + /// + /// The container containing the images to + /// add. + /// + template + void AddImages(const std::vector &images, + typename std::enable_if::value && + sizeof(T) == sizeof(SiImage_t)>::type * = nullptr) { + long error; + navlib::imagearray_t imagearray = {images.data(), images.size()}; + error = m_pImpl->Write(navlib::images_k, imagearray); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Add to the images available to the 3Dconnexion properties utility. + /// + /// The container containing the images to + /// add. + /// + template + void + AddImages(const std::vector &images, + typename std::enable_if::value>::type * = nullptr) { + std::vector siImages; + for (auto const &image : images) { + siImages.push_back(static_cast(image)); + } + + const navlib::imagearray_t imagearray = {siImages.data(), siImages.size()}; + long error = m_pImpl->Write(navlib::images_k, imagearray); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Writes the value of a property to the navlib. + /// + /// The name of the navlib property to + /// write. + /// The to write. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Write(const std::string &propertyName, const navlib::value &value) override { + return m_pImpl->Write(propertyName, value); + } + + /// + /// Reads the value of a navlib property. + /// + /// The name of the navlib property to + /// read. + /// The to read. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Read(const std::string &propertyName, navlib::value &value) const override { + return m_pImpl->Read(propertyName, value); + } + + /// + /// Reads the value of a navlib string property. + /// + /// The name of the navlib property to + /// read. + /// The value of the property. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Read(const std::string &propertyName, std::string &string) const override { + return m_pImpl->Read(propertyName, string); + } + +protected: + // IEvents overrides + /// + /// Default for SetSettingsChanged. + /// + /// The change count. + /// navlib::navlib_errc::function_not_supported error. + long SetSettingsChanged(long count) override { + (void)count; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Default for SetKeyPress. + /// + /// The virtual key code of the key pressed. + /// navlib::navlib_errc::function_not_supported error. + long SetKeyPress(long vkey) override { + (void)vkey; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Default for SetKeyRelease. + /// + /// The virtual key code of the key pressed. + /// navlib::navlib_errc::function_not_supported error. + long SetKeyRelease(long vkey) override { + (void)vkey; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + +protected: + std::error_code make_error_code(long result_code) const { + int errc = result_code & 0xffff; + int facility = result_code >> 16 & 0x7fff; + if (facility == FACILITY_NAVLIB) { + return std::error_code(errc, navlib_category); + } + return std::error_code(errc, std::generic_category()); + } + +protected: + bool m_enabled; + std::string m_profileHint; + std::shared_ptr m_pImpl; +}; +} // namespace ActionInput +} // namespace SpaceMouse +} // namespace TDx +#endif // CInputAction_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CActionInputImpl.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CActionInputImpl.hpp new file mode 100644 index 00000000..4a50987e --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CActionInputImpl.hpp @@ -0,0 +1,187 @@ +#ifndef CActionInputImpl_HPP_INCLUDED +#define CActionInputImpl_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id$ +// +// +#include +#include +#include + +// stdlib +#include +#include +#include +#include + +// navlib +#include +#include + +namespace TDx { +namespace SpaceMouse { +namespace ActionInput { +/// +/// Implementation for creating a shared pointer. +/// +class CActionInputImpl : public Navigation3D::INavlib, +#if defined(_MSC_VER) && _MSC_VER < 1800 + public IActionAccessors, +#else + private IActionAccessors, +#endif + public std::enable_shared_from_this { + typedef CActionInputImpl this_type; + + friend std::shared_ptr + std::static_pointer_cast( + const std::shared_ptr &) NOEXCEPT; + + /// + /// Make the constructors private to force creation of a shared pointer. + /// + CActionInputImpl() = default; + CActionInputImpl(IActionAccessors *iclient) : m_iclient(iclient) { + } + +public: + /// + /// Creates a new instance of the CNavlibImpl class. + /// + /// pointer to the instance implementing the IAccessors interface. + /// true to use multi-threading, false for single-threaded. + /// true for row-major ordered matrices, false for column-major. + /// + /// A to the new CNavlibImpl instance. + /// + static std::shared_ptr CreateInstance(IActionAccessors *iclient, + bool multiThreaded = false) { + return CreateInstance(iclient, multiThreaded, navlib::none); + } + + /// + /// Creates a new instance of the CNavlibImpl class. + /// + /// pointer to the instance implementing the IAccessors interface. + /// true to use multi-threading, false for single-threaded. + /// A combination of the values. + /// + /// A to the new CNavlibImpl instance. + /// + static std::shared_ptr + CreateInstance(IActionAccessors *iclient, bool multiThreaded, navlib::nlOptions_t options) { + if (iclient == nullptr) { + throw std::logic_error("The accessor interface is null"); + } + + // So that std::make_shared<> can be used with the private constructor. + struct make_shared_enabler : public this_type { + make_shared_enabler(IActionAccessors *iclient) : this_type(iclient) { + } + }; + + std::shared_ptr result = std::make_shared(iclient); + result->m_pNavlib = + std::unique_ptr(new Navigation3D::CNavlibInterface( + std::static_pointer_cast(result), multiThreaded, options)); + + return result; + } + + // INavlib implementation + /// + /// Close the connection to the 3D navigation library. + /// + void Close() override { + m_pNavlib->Close(); + } + + /// + /// Opens a connection to the 3D navigation library. + /// + void Open() override { + m_pNavlib->Open(); + } + + /// + /// Opens a connection to the 3D navigation library + /// + /// The name of the 3Dconnexion profile to use. + /// The connection to the library is already open. + /// Cannot create a connection to the library. + /// The name of the profile is empty. + void Open(std::string profileName) override { + m_pNavlib->Open(std::move(profileName)); + } + + /// + /// Writes the value of a property to the navlib. + /// + /// The name of the navlib property to + /// write. + /// The to write. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Write(const std::string &propertyName, const navlib::value &value) override { + return m_pNavlib->Write(propertyName, value); + } + + /// + /// Reads the value of a navlib property. + /// + /// The name of the navlib property to + /// read. + /// The to read. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Read(const std::string &propertyName, navlib::value &value) const override { + return m_pNavlib->Read(propertyName, value); + } + + /// + /// Reads the value of a navlib string property. + /// + /// The name of the navlib property to + /// read. + /// The value of the property. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Read(const std::string &propertyName, std::string &string) const override { + return m_pNavlib->Read(propertyName, string); + } + +private: + // IEvents overrides + long SetActiveCommand(std::string commandId) override { + return m_iclient->SetActiveCommand(commandId); + } + long SetSettingsChanged(long change) override { + return m_iclient->SetSettingsChanged(change); + } + long SetKeyPress(long vkey) override { + return m_iclient->SetKeyPress(vkey); + } + long SetKeyRelease(long vkey) override { + return m_iclient->SetKeyRelease(vkey); + } + +private: + IActionAccessors *m_iclient = nullptr; + std::unique_ptr m_pNavlib; +}; +} // namespace ActionInput +} // namespace SpaceMouse +} // namespace TDx +#endif // CNavlibImpl_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CActionNode.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CActionNode.hpp new file mode 100644 index 00000000..659eea62 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CActionNode.hpp @@ -0,0 +1,353 @@ +#ifndef CActionNode_HPP_INCLUDED +#define CActionNode_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CActionNode.hpp 16051 2019-04-09 11:29:53Z mbonk $ +// +// + +// navlib +#include + +// 3dxware +#include + +// stdlib +#include +#include +#include + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +/// +/// The TDx namespace provides support for the types used in the 3DxWare interface. +/// +namespace TDx { +/// +/// Wrapper class for the structure. +/// +class CActionNode : private SiActionNodeEx_t { + typedef SiActionNodeEx_t base_type; + +public: + /// + /// Initializes a new instance of the class. + /// +#if defined(_MSC_VER) && _MSC_VER < 1800 + CActionNode() : base_type() { + base_type::size = sizeof(base_type); + } +#else + CActionNode() + : base_type({sizeof(base_type), SI_ACTIONSET_NODE, nullptr, nullptr, + nullptr, nullptr, nullptr}) { + } +#endif + + /// + /// Constructor a with a label. + /// + /// The unique node identifier. + /// Text to display to the user in the user interface. + /// The of the node. + explicit CActionNode(std::string nodeId, std::string text, SiActionNodeType_t nodeType) +#if defined(_MSC_VER) && _MSC_VER < 1800 + : base_type(), m_id(std::move(nodeId)), m_label(std::move(text)) { + base_type::size = sizeof(base_type); + base_type::type = nodeType; +#else + : base_type({sizeof(base_type), nodeType, nullptr, nullptr, nullptr, nullptr, nullptr}), + m_id(std::move(nodeId)), m_label(std::move(text)) { +#endif + + if (!m_id.empty()) { + base_type::id = m_id.c_str(); + } + + if (!m_label.empty()) { + base_type::label = m_label.c_str(); + } + } + + /// + /// Constructor a with a label and a description for a tooltip. + /// + /// The unique node identifier + /// Text to display to the user in the user interface. + /// Text to display in a tooltip. + /// The of the node. + explicit CActionNode(std::string nodeId, std::string text, std::string tooltip, + SiActionNodeType_t nodeType) +#if defined(_MSC_VER) && _MSC_VER < 1800 + : base_type(), m_id(std::move(nodeId)), m_label(std::move(text)), + m_description(std::move(tooltip)) { + base_type::size = sizeof(base_type); + base_type::type = nodeType; +#else + : base_type({sizeof(base_type), nodeType, nullptr, nullptr, nullptr, nullptr, nullptr}), + m_id(std::move(nodeId)), m_label(std::move(text)), + m_description(std::move(tooltip)) { +#endif + + if (!m_id.empty()) { + base_type::id = m_id.c_str(); + } + + if (!m_label.empty()) { + base_type::label = m_label.c_str(); + } + + if (!m_description.empty()) { + base_type::description = m_description.c_str(); + } + } + + virtual ~CActionNode() { + Tidy(); + } + + /// + /// Move constructor + /// + /// The to use for construction. + CActionNode(CActionNode &&other) NOEXCEPT + : base_type(other), m_id(std::move(other.m_id)), m_label(std::move(other.m_label)), + m_description(std::move(other.m_description)) { + base_type zero = {sizeof(base_type), SI_ACTIONSET_NODE, nullptr, nullptr, nullptr, + nullptr, nullptr}; + static_cast(other) = zero; + + base_type::id = !m_id.empty() ? m_id.c_str() : nullptr; + base_type::label = !m_label.empty() ? m_label.c_str() : nullptr; + base_type::description = !m_description.empty() ? m_description.c_str() : nullptr; + } + + /// + /// Move assignment + /// + /// The to use for construction. + CActionNode &operator=(CActionNode &&other) NOEXCEPT { + static_cast(*this) = static_cast(other); + m_id = std::move(other.m_id); + m_label = std::move(other.m_label); + m_description = std::move(other.m_description); + + base_type zero = {sizeof(base_type), SI_ACTIONSET_NODE, nullptr, nullptr, + nullptr, nullptr, nullptr}; + static_cast(other) = zero; + + base_type::id = !m_id.empty() ? m_id.c_str() : nullptr; + base_type::label = !m_label.empty() ? m_label.c_str() : nullptr; + base_type::description = !m_description.empty() ? m_description.c_str() : nullptr; + + return *this; + } + +#if !defined(_MSC_VER) || _MSC_VER > 1700 + CActionNode(const CActionNode &) = delete; + CActionNode &operator=(const CActionNode &) = delete; +#else +private: + CActionNode(const CActionNode &); + CActionNode &operator=(const CActionNode &); +#endif + +public: + /// + /// Set the child node. + /// + /// The child node. + template void PutChild(Ty_ &&child) { + if (base_type::children) { + delete static_cast(base_type::children); + } + base_type::children = child.release(); + } + + /// + /// Set the next node. + /// + /// The next node. + template void PutNext(Ty_ &&next_) { + if (base_type::next) { + delete static_cast(base_type::next); + } + base_type::next = next_.release(); + } + +#if defined(_MSC_EXTENSIONS) + /// + /// The properties. + /// + __declspec(property(get = GetId, put = PutId)) std::string Id; + __declspec(property(get = GetDescription, put = PutDescription)) std::string Description; + __declspec(property(get = GetLabel, put = PutLabel)) std::string Label; + __declspec(property(get = GetType, put = PutType)) SiActionNodeType_t Type; +#endif + + void PutType(const SiActionNodeType_t value) { + base_type::type = value; + } + + void PutId(std::string value) { + m_id = std::move(value); + base_type::id = m_id.c_str(); + } + + void PutLabel(std::string value) { + m_label = std::move(value); + base_type::label = m_label.c_str(); + } + + void PutDescription(std::string value) { + m_description = std::move(value); + base_type::description = m_description.c_str(); + } + + CActionNode *DetachChild() { + CActionNode *p = static_cast(base_type::children); + base_type::children = nullptr; + return p; + } + + CActionNode *DetachNext() { + CActionNode *p = static_cast(base_type::next); + base_type::next = nullptr; + return p; + } + + CActionNode *GetChild() { + return static_cast(base_type::children); + } + + const CActionNode *GetChild() const { + return static_cast(base_type::children); + } + + CActionNode *GetNext() { + return static_cast(base_type::next); + } + + const CActionNode *GetNext() const { + return static_cast(base_type::next); + } + + std::string GetId() const { + return m_id; + } + + std::string GetLabel() const { + return m_label; + } + + std::string GetDescription() const { + return m_description; + } + + SiActionNodeType_t GetType() const { + return base_type::type; + } + + const SiActionNodeEx_t &GetSiActionNode() const { + return *this; + } + + /// + /// Clears this and the linked nodes. + /// + void clear() { + base_type::id = base_type::label = base_type::description = nullptr; + m_id.clear(); + m_label.clear(); + m_description.clear(); + Tidy(); + } + + /// + /// Returns true if the node is empty and has no linked nodes + /// + /// + bool empty() const { + return m_id.empty() && base_type::next == nullptr && base_type::children == nullptr && + m_label.empty() && m_description.empty(); + } + +private: + void AssignBaseDataValues() { + base_type::id = !m_id.empty() ? m_id.c_str() : nullptr; + base_type::label = !m_label.empty() ? m_label.c_str() : nullptr; + base_type::description = !m_description.empty() ? m_description.c_str() : nullptr; + } + + void Tidy() { + if (base_type::next == nullptr && base_type::children == nullptr) { + return; + } + + CActionNode *nextNode = static_cast(base_type::next); + CActionNode *childrenNodes = static_cast(base_type::children); + + base_type::next = nullptr; + base_type::children = nullptr; + + // Fix to avoid a stack overflow when destructing large lists + // This traverses to the end of the list and deletes from there + std::vector vnodes; + + if (nextNode) { + vnodes.push_back(nextNode); + } + + if (childrenNodes) { + vnodes.push_back(childrenNodes); + } + + size_t i; + for (i = 0; i < vnodes.size(); ++i) { + nextNode = static_cast(vnodes[i]->next); + + childrenNodes = static_cast(vnodes[i]->children); + + if (nextNode) { + vnodes[i]->next = nullptr; + vnodes.push_back(nextNode); + } + + if (childrenNodes) { + vnodes[i]->children = nullptr; + vnodes.push_back(childrenNodes); + } + } + + std::vector::reverse_iterator riter; + for (riter = vnodes.rbegin(); riter != vnodes.rend(); ++riter) { + delete (*riter); + } + } + +private: + std::string m_id; + std::string m_label; + std::string m_description; +}; +} // namespace TDx + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif +#endif // CActionNode_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CCategory.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CCategory.hpp new file mode 100644 index 00000000..02d6e560 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CCategory.hpp @@ -0,0 +1,64 @@ +#ifndef CCategory_HPP_INCLUDED +#define CCategory_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CCategory.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// +#include + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +namespace TDx { +/// +/// Contains types used for programming the SpaceMouse. +/// +namespace SpaceMouse { +/// +/// The helper class implements the node type. +/// +class CCategory : public CCommandTreeNode { + typedef CCommandTreeNode base_type; + +public: + CCategory() { + } + + explicit CCategory(std::string id, std::string name) + : base_type(std::move(id), std::move(name), SiActionNodeType_t::SI_CATEGORY_NODE) { + } + +#if defined(_MSC_VER) && _MSC_VER < 1900 + CCategory(CCategory &&other) : base_type(std::forward(other)) { + } + CCategory &operator=(CCategory &&other) { + base_type::operator=(std::forward(other)); + return *this; + } +#else + CCategory(CCategory &&) = default; + CCategory &operator=(CCategory &&) = default; +#endif +}; +} // namespace SpaceMouse +} // namespace TDx + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif + +#endif // CCategory_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CCommand.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CCommand.hpp new file mode 100644 index 00000000..62c94a7e --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CCommand.hpp @@ -0,0 +1,64 @@ +#ifndef CCommand_HPP_INCLUDED +#define CCommand_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CCommand.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// +#include + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +namespace TDx { +namespace SpaceMouse { +/// +/// The class implements the application command node. +/// +class CCommand : public CCommandTreeNode { + typedef CCommandTreeNode base_type; + +public: + CCommand() { + } + + explicit CCommand(std::string id, std::string name, std::string description) + : base_type(std::move(id), std::move(name), std::move(description), + SiActionNodeType_t::SI_ACTION_NODE) { + } + explicit CCommand(std::string id, std::string name) + : base_type(std::move(id), std::move(name), SiActionNodeType_t::SI_ACTION_NODE) { + } +#if defined(_MSC_VER) && _MSC_VER < 1900 + CCommand(CCommand &&other) : base_type(std::forward(other)) { + } + CCommand &operator=(CCommand &&other) { + base_type::operator=(std::forward(other)); + return *this; + } +#else + CCommand(CCommand &&) = default; + CCommand &operator=(CCommand &&) = default; +#endif +}; +} // namespace SpaceMouse +} // namespace TDx + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif + +#endif // CCommand_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CCommandSet.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CCommandSet.hpp new file mode 100644 index 00000000..c74c2305 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CCommandSet.hpp @@ -0,0 +1,60 @@ +#ifndef CCommandSet_HPP_INCLUDED +#define CCommandSet_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CCommandSet.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// +#include + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +namespace TDx { +namespace SpaceMouse { +/// +/// The helper class implements the node type. +/// +class CCommandSet : public CCommandTreeNode { + typedef CCommandTreeNode base_type; + +public: + CCommandSet() { + } + + explicit CCommandSet(std::string id, std::string name) + : base_type(std::move(id), std::move(name), SiActionNodeType_t::SI_ACTIONSET_NODE) { + } +#if defined(_MSC_VER) && _MSC_VER < 1900 + CCommandSet(CCommandSet &&other) : base_type(std::forward(other)) { + } + CCommandSet &operator=(CCommandSet &&other) { + base_type::operator=(std::forward(other)); + return *this; + } +#else + CCommandSet(CCommandSet &&) = default; + CCommandSet &operator=(CCommandSet &&) = default; +#endif +}; +} // namespace SpaceMouse +} // namespace TDx + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif + +#endif // CCommandSet_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CCommandTreeNode.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CCommandTreeNode.hpp new file mode 100644 index 00000000..24db10a5 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CCommandTreeNode.hpp @@ -0,0 +1,288 @@ +#ifndef CCommandTreeNode_HPP_INCLUDED +#define CCommandTreeNode_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CCommandTreeNode.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// +#include + +// stdlib +#include +#include +#include + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +namespace TDx { +template class raw_linkedlist_iterator { +public: + typedef std::input_iterator_tag iterator_category; + typedef Ty_ value_type; + typedef ptrdiff_t difference_type; + typedef Ty_ *pointer; + typedef Ty_ &reference; + +public: + raw_linkedlist_iterator(Ty_ *ptr_ = nullptr) : MyPtr_(ptr_) { + } + + raw_linkedlist_iterator(const raw_linkedlist_iterator &_other) : MyPtr_(_other.MyPtr_) { + } + + raw_linkedlist_iterator &operator=(const raw_linkedlist_iterator &_other) { + MyPtr_ = _other.MyPtr_; + return *this; + } + + raw_linkedlist_iterator &operator=(Ty_ *ptr_) { + MyPtr_ = ptr_; + return *this; + } + + // accessors + Ty_ &operator*() { + return *MyPtr_; + } + Ty_ const &operator*() const { + return *MyPtr_; + } + Ty_ *operator->() { + return MyPtr_; + } + Ty_ const *operator->() const { + return MyPtr_; + } + + raw_linkedlist_iterator &operator++() { + if (MyPtr_) + MyPtr_ = MyPtr_->GetNext(); + return *this; + } + + raw_linkedlist_iterator &operator--() { + if (doubled_linked) { + if (MyPtr_) + MyPtr_ = MyPtr_->GetPrevious(); + } else { + throw std::logic_error("Not Supported"); + } + return *this; + } + + bool operator<(raw_linkedlist_iterator const &rhs) const { + if (!MyPtr_) + return false; + else if (!rhs.MyPtr_) + return true; + return (MyPtr_ < rhs.MyPtr_); + } + + bool operator<=(raw_linkedlist_iterator const &rhs) const { + if (MyPtr_ == rhs.MyPtr_) + return true; + return operator<(rhs); + } + + bool operator>(raw_linkedlist_iterator const &rhs) const { + return !operator<=(rhs); + } + + bool operator>=(raw_linkedlist_iterator const &rhs) const { + return !operator<(rhs); + } + + operator bool() const { + return MyPtr_ != nullptr; + } + +protected: + Ty_ *MyPtr_; +}; + +/// +/// Tree container for CActionNode. +/// +/// The tree is implemented as a singularly linked list. +class CCommandTree : public CActionNode { +public: + typedef CActionNode base_type; + typedef CActionNode const const_base_type; + typedef CActionNode const &const_base_ref_type; + typedef CActionNode const *const_base_ptr_type; + typedef CCommandTree self_type; + +public: + typedef CCommandTree &reference; + typedef CCommandTree const &const_reference; + + typedef raw_linkedlist_iterator iterator; + typedef raw_linkedlist_iterator const_iterator; + + CCommandTree() { + } + + explicit CCommandTree(std::string id, std::string label, std::string description, + SiActionNodeType_t type) + : base_type(std::move(id), std::move(label), std::move(description), type) { + } + + explicit CCommandTree(std::string id, std::string label, SiActionNodeType_t type) + : base_type(std::move(id), std::move(label), type) { + } + +#if defined(_MSC_VER) && _MSC_VER < 1900 + CCommandTree(CCommandTree &&other) : base_type(std::forward(other)) { + } + CCommandTree &operator=(CCommandTree &&other) { + base_type::operator=(std::forward(other)); + return *this; + } + +private: + CCommandTree(const CCommandTree &) { + } + const CCommandTree &operator=(const CCommandTree &){}; +#else + CCommandTree(CCommandTree &&) = default; + CCommandTree &operator=(CCommandTree &&) = default; + // No copying + CCommandTree(const CCommandTree &) = delete; + const CCommandTree &operator=(const CCommandTree &) = delete; +#endif // defined(_MSC_VER) && _MSC_VER<1900 + +public: + void push_back(base_type &&value) { +#if (defined(_MSC_VER) && _MSC_VER < 1900) + std::unique_ptr node(new base_type(std::forward(value))); +#else + std::unique_ptr node = std::make_unique(std::forward(value)); +#endif + push_back(std::move(node)); + } + + template + void + push_back(std::unique_ptr &&value, + typename std::enable_if::value>::type * = nullptr) { + base_type *last = this->GetChild(); + if (!last) { + PutChild(std::unique_ptr(static_cast(value.release()))); + } else { + while (last->GetNext() != nullptr) { + last = last->GetNext(); + } + last->PutNext(std::unique_ptr(static_cast(value.release()))); + } + } + + void push_front(base_type &&value) { +#if (defined(_MSC_VER) && _MSC_VER < 1900) + std::unique_ptr node(new base_type(std::forward(value))); +#else + std::unique_ptr node = std::make_unique(std::forward(value)); +#endif + push_front(std::move(node)); + } + + void push_front(std::unique_ptr &&value) { + value->PutNext(std::unique_ptr(DetachChild())); + PutChild(std::forward>(value)); + } + + const_reference back() const { + const base_type *last = this->GetChild(); + if (!last) { + return *this; + } + + while (last->GetNext() != nullptr) { + last = last->GetNext(); + } + return *static_cast(last); + } + + reference back() { + base_type *last = this->GetChild(); + if (!last) { + return *this; + } + + while (last->GetNext() != nullptr) { + last = last->GetNext(); + } + return *static_cast(last); + } + + void clear() { + base_type *head = this->DetachChild(); + if (head) { + head->clear(); + } + } + + const_reference front() const { + const base_type *head = this->GetChild(); + if (!head) { + return *this; + } + return *static_cast(head); + } + + reference front() { + base_type *head = this->GetChild(); + if (!head) { + return *this; + } + return *static_cast(head); + } + + const_iterator begin() const { + if (empty()) { + return end(); + } + return const_iterator(this->GetChild()); + } + + iterator begin() { + if (empty()) { + return end(); + } + return iterator(this->GetChild()); + } + + bool empty() const { + return (this->GetChild() == nullptr); + } + + const_iterator end() const { + return nullptr; + } + + iterator end() { + return nullptr; + } +}; + +typedef CCommandTree CCommandTreeNode; +} // namespace TDx + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif + +#endif // CCommandTreeNode_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CCookieCollection.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CCookieCollection.hpp new file mode 100644 index 00000000..c77ce263 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CCookieCollection.hpp @@ -0,0 +1,102 @@ +#ifndef CCookieCollection_HPP_INCLUDED +#define CCookieCollection_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CCookieCollection.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include +// stdlib +#include +#include +#include +#if (!defined(_MSC_VER) || (_MSC_VER > 1600)) +#include +#else +#pragma warning(disable : 4482) // non-standard +#include +#include +namespace std { +using boost::lock_guard; +using boost::mutex; +using boost::unique_lock; +} // namespace std +#endif + +namespace TDx { +namespace SpaceMouse { +/// +/// The class maps a cookie to a shared_ptr. +/// +template +class CCookieCollection : protected std::map> { + typedef std::map> map_t; + +public: + typedef typename map_t::size_type size_type; + + /// + /// Gets the corresponding to the passed in cookie. + /// + /// The to search for. + /// The . + /// If the cookie does not exist. + std::shared_ptr at(const navlib::param_t &cookie) { + std::lock_guard guard(m_mutex); + typename map_t::iterator iter = map_t::find(cookie); + if (iter != map_t::end()) { + return iter->second; + } + + throw std::out_of_range("Cookie does not exist in the Collection"); + } + + /// + /// Removes the elements that match the cookie. + /// + /// The cookie entry to remove. + /// The number of elements that have been removed. + size_type erase(const navlib::param_t &cookie) { + std::lock_guard guard(m_mutex); + return map_t::erase(cookie); + } + + /// + /// Inserts a and returns a cookie that is needed to retrieve it later. + /// + /// The to insert. + /// A cookie that is needed to find the shared pointer. + navlib::param_t insert(std::shared_ptr sp) { + navlib::param_t param = 0; + if (sp) { + std::lock_guard guard(m_mutex); + do { + using namespace std::chrono; + param = static_cast( + duration_cast(high_resolution_clock::now().time_since_epoch()).count()); + } while (map_t::find(param) != map_t::end()); + (*this)[param] = std::move(sp); + } + return param; + } + +protected: + /// + /// When changing the contents of the collection always use the mutex as a guard + /// + std::mutex m_mutex; +}; +} // namespace SpaceMouse +} // namespace TDx +#endif // CCookieCollection_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CHitTest.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CHitTest.hpp new file mode 100644 index 00000000..e1178b1c --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CHitTest.hpp @@ -0,0 +1,132 @@ +#ifndef CHitTest_HPP_INCLUDED +#define CHitTest_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CHitTest.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// 01/20/14 MSB Initial design +// + +// 3dxware +#include + +namespace TDx { +namespace SpaceMouse { +/// +/// Class can be used to hold the hit-test properties. +/// +template class CHitTest { +public: + typedef point_ point_type; + typedef vector_ vector_type; + +public: + /// + /// Creates a new instance of the class. + /// + CHitTest() : m_aperture(1), m_dirty(false), m_selectionOnly(false) { + } + +#if defined(_MSC_EXTENSIONS) + /// + /// Property accessors + /// + __declspec(property(get = GetDirection, put = PutDirection)) vector_type Direction; + __declspec(property(get = GetLookFrom, put = PutLookFrom)) point_type LookFrom; + __declspec(property(get = GetLookingAt, put = PutLookingAt)) point_type LookingAt; + __declspec(property(get = GetIsDirty, put = PutIsDirty)) bool IsDirty; + __declspec(property(get = GetAperture, put = PutAperture)) double Aperture; + __declspec(property(get = GetSelectionOnly, put = PutSelectionOnly)) bool SelectionOnly; +#endif + + /// + /// Gets or sets the ray direction. + /// + void PutDirection(vector_type value) { + if (!m_dirty) { + m_dirty = static_cast(m_direction != value); + } + m_direction = std::move(value); + } + vector_type GetDirection() const { + return m_direction; + } + + /// + /// Gets or sets the ray origin. + /// + void PutLookFrom(point_type value) { + if (!m_dirty) { + m_dirty = static_cast(m_lookFrom != value); + } + m_lookFrom = std::move(value); + } + const point_type GetLookFrom() const { + return m_lookFrom; + } + + /// + /// Gets or sets the ray hit test result location. + /// + void PutLookingAt(point_type value) { + m_lookingAt = std::move(value); + m_dirty = false; + } + const point_type GetLookingAt() const { + return m_lookingAt; + } + + /// + /// Gets or sets a value indicating if a the parameters have changed since the last hit calculation. + /// + void PutIsDirty(bool value) { + m_dirty = value; + } + bool GetIsDirty() const { + return m_dirty; + } + + /// + /// Gets or sets the ray diameter / aperture on the near clipping plane. + /// + void PutAperture(double value) { + m_dirty = (m_aperture != value); + m_aperture = value; + } + double GetAperture() const { + return m_aperture; + } + + /// + /// Gets or sets a value indicating whether the hit-testing is limited to the selection set. + /// + void PutSelectionOnly(bool value) { + m_selectionOnly = value; + } + bool GetSelectionOnly() const { + return m_selectionOnly; + } + +private: + double m_aperture; + mutable bool m_dirty; + vector_type m_direction; + point_type m_lookFrom; + mutable point_type m_lookingAt; + bool m_selectionOnly; +}; +} // namespace SpaceMouse +} // namespace TDx +#endif // CHitTest_HPP_INCLUDED + diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CImage.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CImage.hpp new file mode 100644 index 00000000..e3af17d5 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CImage.hpp @@ -0,0 +1,322 @@ +#ifndef CImage_HPP_INCLUDED +#define CImage_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CImage.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// + +// stdlib +#include +#include + +// 3dxware +#include + +#if defined(_MSC_VER) && _MSC_VER<1800 +// #pragma warning(1 : 4519) // convert error C4519 'default template arguments are only allowed on a class template' to warning +#pragma warning(disable : 4519) // disable error C4519 +#if _MSC_VER < 1700 +#pragma warning(disable : 4482) // warning C4482: nonstandard extension used +#endif +#endif + +#ifdef __APPLE__ +#define IS_INTRESOURCE_(x) false +#elif !defined(IS_INTRESOURCE_) +#define IS_INTRESOURCE_(_r) (((reinterpret_cast(_r)) >> 16) == 0) +#endif + +namespace TDx { +/// +/// A class that represents the SiImage_t structure. +/// +class CImage { +public: + /// + /// Initializes a new instance of the class. + /// + CImage() : m_type(SiImageType_t::e_none), m_index(0) { + } + + /// + /// Initializes a new instance of the class from a . + /// + /// + explicit CImage(const SiImage_t &siImage) : m_id(siImage.id), m_type(siImage.type) { + if (siImage.size != sizeof(SiImage_t)) { + throw std::invalid_argument("Invalid SiImage_t structure."); + } + + switch (m_type) { + case SiImageType_t::e_image_file: + m_source = siImage.file.file_name; + m_index = siImage.file.index; + break; + case SiImageType_t::e_resource_file: + m_source = siImage.resource.file_name; + m_resourceId = siImage.resource.id; + m_resourceType = siImage.resource.type; + m_index = siImage.resource.index; + break; + case SiImageType_t::e_image: + m_source.assign(reinterpret_cast(siImage.image.data), siImage.image.size); + m_index = siImage.image.index; + break; + case SiImageType_t::e_glyph: + m_source = siImage.glyph.font_family; + m_glyphs = siImage.glyph.glyphs; + break; + case SiImageType_t::e_none: + default: + break; + } + } + +#if defined(_MSC_EXTENSIONS) + /// + /// Gets or sets the image id. + /// + __declspec(property(get = GetId, put = PutId)) std::string Id; + + /// + /// Gets or sets the resource id. + /// + __declspec(property(get = GetResourceId, put = PutResourceId)) std::string ResourceId; + + /// + /// Gets the image type. + /// + __declspec(property(get = GetType)) SiImageType_t Type; +#endif + + /// + /// Sets the id of the image. + /// + /// A representing the name or id of the image. + void PutId(std::string id) { + m_id = std::move(id); + } + + /// + /// Gets the image id. + /// + /// A representing the name or id of the image. + std::string GetId() const { + return m_id; + } + + /// + /// Sets the id of the resource in the resource file. + /// + /// A representing the name or id of the image in the + /// resource file. + /// For example for Microsoft resource libraries MAKEINTRESOURCE(216) = "#216". + void PutResourceId(std::string id) { + m_resourceId = std::move(id); + } + + /// + /// Gets the resource id. + /// + /// A representing the name or id of the image. + /// For example for Microsoft resource libraries MAKEINTRESOURCE(216) = "#216". + std::string GetResourceId() const { + return m_resourceId; + } + + /// + /// Gets the image type. + /// + /// One of . + SiImageType_t GetType() const { + return m_type; + } + + + /// + /// Assigns image data to the instance. + /// + /// The image data. The image may be in any format that can be loaded by + /// Gdiplus::Bitmap::FromStream() or is in a recognizable svg format. + /// true if successful, otherwise false. + /// The type is set to . + bool AssignImage(std::string buffer, uint32_t index = 0) { + m_source = std::move(buffer); + m_type = e_image; + m_index = index; + m_resourceId.clear(); + m_resourceType.clear(); + return true; + } + + /// + /// Initializes a new instance of the class that contains the data for an + /// image held in a resource file. + /// + /// The name of the resource file. + /// The name or id of the image in the resource file. i.e. + /// MAKEINTRESOURCE(216) = "#216". + /// The type of the resource in the resource file. i.e. RT_BITMAP = + /// "#2". + /// The index in a multi-image resource. + /// The id of the command to associate with this image. + /// A instance. + template + static T FromResource(const std::string &resourceFile, const char *resourceId, + const char *resourceType, uint32_t index = 0, const char *id = nullptr) { + + std::string r_id; + if (resourceId != nullptr) { + if (IS_INTRESOURCE_(resourceId)) { + std::ostringstream stream; + stream << "#" << reinterpret_cast(resourceId); + r_id = stream.str(); + } else { + r_id = resourceId; + } + } + + std::string r_type; + if (resourceType != nullptr) { + if (IS_INTRESOURCE_(resourceType)) { + std::ostringstream stream; + stream << "#" << reinterpret_cast(resourceType); + r_type = stream.str(); + } else { + r_type = resourceType; + } + } + + T image(resourceFile, r_id, r_type, id != nullptr ? id : "", e_resource_file, + index); + return image; + } + + /// + /// Initializes a new instance of the class that contains the data for an + /// image in a file. + /// + /// The name of the image file. + /// The index in a multi-image file. + /// The id of the command to associate with this image. + /// A instance. + template + static T FromFile(const std::string &filename, uint32_t index = 0, const char *id = nullptr) { + T image(filename, id != nullptr ? id : "", e_image_file, index); + return image; + } + + /// + /// Initializes a new instance of the class that contains the data for an + /// image in a font. + /// + /// The name of the font family. + /// The glyphs from which to create the image. + /// The id of the command to associate with this image. + /// A instance. + template + static T FromFont(const std::string &fontFamily, const std::wstring &glyph, + const char *id = nullptr) { + T image(fontFamily, glyph, id != nullptr ? id : "", e_glyph); + return image; + } + + /// + /// Initializes a new instance of the CImage class that contains the data for an image in a buffer. + /// + /// The image data. The image may be in any format that can be loaded by + /// Gdiplus::Bitmap::FromStream() or is in a recognizable svg format. + /// The index in a multi-image file. + /// The id of the command to associate with this image. + /// A instance. + template + static T FromData(const std::string &buffer, uint32_t index = 0, const char *id = nullptr) { + T image(buffer, id != nullptr ? id : "", e_image, index); + return image; + } + + /// + /// Returns an view of the instance. + /// + /// A . + operator SiImage_t() const { + SiImage_t siImage = { + sizeof(SiImage_t), SiImageType_t::e_none, m_id.c_str(), {}}; + switch (m_type) { + case SiImageType_t::e_image_file: + siImage.type = m_type; + siImage.file.file_name = m_source.c_str(); + siImage.file.index = m_index; + break; + case SiImageType_t::e_resource_file: + siImage.type = m_type; + siImage.resource.file_name = m_source.c_str(); + siImage.resource.id = m_resourceId.c_str(); + siImage.resource.type = m_resourceType.c_str(); + siImage.resource.index = m_index; + break; + case SiImageType_t::e_image: + siImage.type = m_type; + siImage.image.data = reinterpret_cast(m_source.data()); + siImage.image.size = m_source.size(); + siImage.image.index = m_index; + break; + case SiImageType_t::e_glyph: + siImage.type = m_type; + siImage.glyph.font_family = m_source.c_str(); + siImage.glyph.glyphs = m_glyphs.c_str(); + break; + case SiImageType_t::e_none: + break; + } + + return siImage; + } + + /// + /// checks whether the image is empty. + /// + /// true if the image contains data, otherwise false. + bool empty() const { + return m_type == SiImageType_t::e_none || (m_type == SiImageType_t::e_image && m_source.empty()); + } + +protected: + CImage(std::string source, std::wstring glyphs, std::string id, SiImageType_t type) + : m_source(std::move(source)), m_glyphs(std::move(glyphs)), m_id(std::move(id)), m_type(type) { + } + + CImage(std::string source, std::string id, SiImageType_t type, uint32_t index = 0) + : m_source(std::move(source)), m_id(std::move(id)), m_type(type), m_index(index) { + } + + CImage(std::string source, std::string resourceName, std::string resourceType, std::string id, + SiImageType_t type, uint32_t index = 0) + : m_source(std::move(source)), m_resourceId(std::move(resourceName)), + m_resourceType(std::move(resourceType)), m_id(std::move(id)), m_type(type), m_index(index) { + } + +protected: + std::string m_source; + std::string m_resourceId; + std::string m_resourceType; + std::wstring m_glyphs; + std::string m_id; + SiImageType_t m_type; + uint32_t m_index; +}; +} // namespace TDx +#endif // CImage_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CNavigation3D.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CNavigation3D.hpp new file mode 100644 index 00000000..3ea8e1e7 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CNavigation3D.hpp @@ -0,0 +1,568 @@ +#ifndef CNavigation3D_HPP_INCLUDED +#define CNavigation3D_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CNavigation3D.hpp 16056 2019-04-10 13:42:31Z mbonk $ +// +// + +// SpaceMouse +#include +#include +#include +#include +#include +#include +#include +#include + +// stdlib +#include +#include +#include +#if (!defined(_MSC_VER) || (_MSC_VER > 1600)) +#include +#else +#include +namespace std { +namespace chrono = boost::chrono; +using boost::milli; +} // namespace std +#endif + +// navlib +#include +#include + +namespace TDx { +namespace SpaceMouse { +/// +/// Contains types that support 3DMouse navigation. +/// +namespace Navigation3D { +/// +/// The base class for 3D navigation implements defaults for the interface. +/// +/// This class can be used as the base class for the application specific implementation of +/// the accessors. +class CNavigation3D : public INavlibProperty, protected IAccessors { +public: + /// + /// The timing source for the frame time. + /// + enum TimingSource { + /// + /// The space mouse is the source of the frame timing. + /// + SpaceMouse = 0, + + /// + /// The application is the source of the frame timing. + /// + Application = 1, + }; + +public: + /// + /// Initializes a new instance of the CNavigation3D class. + /// + /// true to use multi-threading, false for single-threaded. + /// true for column vectors, false for row vectors as used by OpenGL. + /// + /// The default is single-threaded, row vectors + explicit CNavigation3D(bool multiThreaded = false, bool columnVectors = false) + : m_enabled(false), m_pImpl(CNavlibImpl::CreateInstance(this, multiThreaded, columnVectors)) { + } + + /// + /// Initializes a new instance of the CNavigation3D class. + /// + /// true to use multi-threading, false for single-threaded. + /// A combination of the values. + explicit CNavigation3D(bool multiThreaded, navlib::nlOptions_t options) + : m_enabled(false), m_pImpl(CNavlibImpl::CreateInstance(this, multiThreaded, options)) { + } + +#if defined(_MSC_EXTENSIONS) + /// + /// Gets or sets a value indicating whether the 3DMouse navigation is enabled. + /// + __declspec(property(get = IsEnabled, put = EnableNavigation)) bool Enable; + + /// + /// Gets or sets the animation frame time. + /// + __declspec(property(get = GetFrameTime, + put = PutFrameTime)) std::chrono::high_resolution_clock::time_point FrameTime; + + /// + /// Gets or sets the frame timing source. + /// + __declspec(property(get = GetFrameTimingSource, + put = PutFrameTimingSource)) TimingSource FrameTiming; + /// + /// Gets or sets the text to pass to the 3Dconnexion driver to use in Properties Utility. + /// + /// If the connection to the navlib is already open, the connection is closed and + /// reopened. + __declspec(property(get = GetProfileHint, put = PutProfileHint)) std::string Profile; + + /// + /// Gets or sets a value representing the active command set. + /// + /// + __declspec(property(get = GetActiveCommands, put = PutActiveCommands)) std::string ActiveCommands; + +#endif + + /// + /// Gets a value indicating whether 3DMouse navigation is enabled. + /// + /// true if enabled, otherwise false. + bool IsEnabled() const { + return m_enabled; + } + + /// + /// Sets a value indicating whether 3DMouse navigation is enabled. + /// + /// true to enable, false to disable. + /// The text for the '3Dconnexion Properties' is + /// empty. + /// Cannot create a connection to the library. + void EnableNavigation(bool value) { + if (m_enabled == value) { + return; + } + if (value) { + m_pImpl->Open(m_profileHint); + m_enabled = true; + } else { + m_pImpl->Close(); + m_enabled = false; + } + } + + /// + /// Sets a value indicating whether 3DMouse navigation is enabled. + /// + /// true to enable, false to disable. + /// The contains the error if something goes + /// wrong. + /// The text for the '3Dconnexion Properties' is + /// empty. + /// Cannot create a connection to the library. + void EnableNavigation(bool value, std::error_code &ec) NOEXCEPT { + try { + EnableNavigation(value); + } +#if defined(_DEBUG) && defined(TRACE_NAVLIB) + catch (const std::system_error &e) { + ec = e.code(); + std::cout << "system_error exception thrown in EnableNavigation(" << value << ") 0x" << std::hex + << ec.value() << std::dec << ", " << ec.message() << ", " << e.what() << "\n"; + } catch (const std::invalid_argument &e) { + ec = std::make_error_code(std::errc::invalid_argument); + std::cout << "invalid_argument exception thrown in EnableNavigation(" << value << ") 0x" + << std::hex << ec.value() << std::dec << ", " << ec.message() << ", " << e.what() + << "\n"; + } catch (const std::exception &e) { + ec = std::make_error_code(std::errc::io_error); + std::cout << "exception thrown in EnableNavigation(" << value << ") 0x" << std::hex << ec.value() + << std::dec << ", " << ec.message() << ", " << e.what() << "\n"; + } +#else + catch (const std::system_error &e) { + ec = e.code(); + } catch (const std::invalid_argument &) { + ec = std::make_error_code(std::errc::invalid_argument); + } catch (const std::exception &) { + ec = std::make_error_code(std::errc::io_error); + } +#endif + } + + /// + /// Gets or sets the animation frame time. + /// + std::chrono::high_resolution_clock::time_point GetFrameTime() { + return m_frameTime; + } + void PutFrameTime(std::chrono::high_resolution_clock::time_point value) { + if (m_frameTime != value) { + m_frameTime = std::move(value); + auto elapsed = std::chrono::duration_cast>( + m_frameTime.time_since_epoch()); + m_pImpl->Write(navlib::frame_time_k, elapsed.count()); + } + } + + /// + /// Gets or sets the frame timing source. + /// + TimingSource GetFrameTimingSource() { + return m_frameTimingSource; + } + void PutFrameTimingSource(TimingSource value) { + if (m_frameTimingSource != value) { + m_frameTimingSource = value; + m_pImpl->Write(navlib::frame_timing_source_k, static_cast(value)); + } + } + + /// + /// Gets or sets the text to pass to the 3Dconnexion driver to use in Properties Utility. + /// + /// If the connection to the navlib is already open, the connection is closed and + /// reopened. + std::string GetProfileHint() const { + return m_profileHint; + } + void PutProfileHint(std::string value) { + if (m_profileHint != value) { + m_profileHint = std::move(value); + if (IsEnabled()) { + EnableNavigation(false); + EnableNavigation(true); + } + } + } + + /// + /// Gets or sets a value representing the active command set. + /// + /// + std::string GetActiveCommands() const { + std::string result; + long error = m_pImpl->Read(navlib::commands_activeSet_k, result); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + return result; + } + void PutActiveCommands(const std::string &id) { + long error = m_pImpl->Write(navlib::commands_activeSet_k, id); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Add commands to the sets of commands. + /// + /// The to add. + /// + void AddCommands(const CCommandTree &commands) { + const SiActionNodeEx_t *pnode = &commands.GetSiActionNode(); + long error = m_pImpl->Write(navlib::commands_tree_k, pnode); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Add a set of commands to the sets of commands. + /// + /// The to add. + /// + void AddCommandSet(const CCommandSet &commands) { + AddCommands(commands); + } + + /// + /// Add to the images available to the 3Dconnexion properties utility. + /// + /// The container containing the images to + /// add. + /// + template + void AddImages(const std::vector &images, + typename std::enable_if::value && + sizeof(T) == sizeof(SiImage_t)>::type * = nullptr) { + long error; + navlib::imagearray_t imagearray = {images.data(), images.size()}; + error = m_pImpl->Write(navlib::images_k, imagearray); + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Add to the images available to the 3Dconnexion properties utility. + /// + /// The container containing the images to + /// add. + /// + template + void + AddImages(const std::vector &images, + typename std::enable_if::value>::type * = nullptr) { + std::vector siImages; + for (auto iter = images.begin(); iter != images.end(); ++iter) { + siImages.push_back(static_cast(*iter)); + } + navlib::imagearray_t imagearray = {siImages.data(), siImages.size()}; + long error = m_pImpl->Write(navlib::images_k, imagearray); + + if (error != 0) { + throw std::system_error(make_error_code(error)); + } + } + + /// + /// Writes the value of a property to the navlib. + /// + /// The name of the navlib property to + /// write. + /// The to write. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Write(const std::string &propertyName, const navlib::value &value) override { + return m_pImpl->Write(propertyName, value); + } + + /// + /// Reads the value of a navlib property. + /// + /// The name of the navlib property to + /// read. + /// The to read. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Read(const std::string &propertyName, navlib::value &value) const override { + return m_pImpl->Read(propertyName, value); + } + + /// + /// Reads the value of a navlib string property. + /// + /// The name of the navlib property to + /// read. + /// The value of the property. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Read(const std::string &propertyName, std::string &string) const override { + return m_pImpl->Read(propertyName, string); + } + +protected: + // IEvents overrides + /// + /// Default for SetSettingsChanged. + /// + /// The change count. + /// navlib::navlib_errc::function_not_supported error. + long SetSettingsChanged(long count) override { + (void)count; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Default for SetKeyPress. + /// + /// The virtual key code of the key pressed. + /// navlib::navlib_errc::function_not_supported error. + long SetKeyPress(long vkey) override { + (void)vkey; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Default for SetKeyRelease. + /// + /// The virtual key code of the key pressed. + /// navlib::navlib_errc::function_not_supported error. + long SetKeyRelease(long vkey) override { + (void)vkey; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// ISpace3D overrides + /// + /// Gets the coordinate system used by the client. + /// + /// The coordinate system . + /// 0 = no error, otherwise <0. + /// The matrix describes the applications coordinate frame in the navlib coordinate + /// system. i.e. the application to navlib transform. The default is a right-handed coordinate + /// system X-right, Z-up, Y-in (column-major) + long GetCoordinateSystem(navlib::matrix_t &matrix) const override { + // Use the right-handed coordinate system X-right, Y-up, Z-out (same as navlib) + navlib::matrix_t cs = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + + // Use the right-handed coordinate system X-right, Z-up, Y-in (column-major/row vectors) + // navlib::matrix_t cs = {{{1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1}}}; + + matrix = cs; + + return 0; + } + + /// + /// Gets the orientation of the front view. + /// + /// The front view transform . + /// 0 = no error, otherwise <0. + /// The default is the inverse of the coordinate system, i.e. in this case the identity + /// matrix. + long GetFrontView(navlib::matrix_t &matrix) const override { + navlib::matrix_t front = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + matrix = front; + return 0; + } + + // IModel overrides + /// + /// Gets the length of the model/world unit in meters. + /// + /// The length of a model/world unit in meters. + /// 0 = no error, otherwise <0. + /// + /// The conversion factor is used by the Navigation Library to calculate the height above + /// the floor in walk mode and the speed in the first-person motion model. + /// The Navigation Library assumes that this value does not change and it is only queried + /// once. + /// + long GetUnitsToMeters(double &meters) const override { + (void)meters; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Gets the plane equation of the floor. + /// + /// The plane equation of the floor plane. + /// 0 = no error, otherwise <0. + /// + /// The plane equation is used by the Navigation Library to determine the floor for the + /// walk navigation mode, where the height of the eye is fixed to 1.5m above the floor plane. + /// The floor need not be parallel to the world ground plane. + /// + long GetFloorPlane(navlib::plane_t &floor) const override { + (void)floor; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + // IState overrides + /// + /// Is called when the navigation library starts or stops a navigation transaction. + /// + /// The transaction number: >0 begin, ==0 end. + /// 0 = no error, otherwise <0. + long SetTransaction(long transaction) override { + (void)transaction; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Is called when the navigation instance starts or stops a sequence of motion frames. + /// + /// The motion flag: true = start, false = end. + /// 0 = no error, otherwise <0. + /// This marks the start and end of user interaction with the scene using the + /// 3D Mouse. + long SetMotionFlag(bool motion) override { + (void)motion; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Gets the camera's target. + /// + /// The position of the camera target in world coordinates. + /// 0 = no error, otherwise <0. + /// Free cameras do not have a target. + long GetCameraTarget(navlib::point_t &target) const override { + (void)target; + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + } + /// + /// Gets the view's construction plane. + /// + /// The plane equation of the construction plane. + /// 0 = no error, otherwise <0. + /// Required to disable rotations when constructing. + long GetViewConstructionPlane(navlib::plane_t &plane) const override { + (void)plane; + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + } + + /// + /// Gets a value indicating whether the view can be rotated. + /// + /// true if the view can be rotated, false otherwise. + /// 0 = no error, otherwise <0. + /// For paper space return false. + long GetIsViewRotatable(navlib::bool_t &isRotatable) const override { + isRotatable = true; + return 0; + } + + /// + /// Gets the distance to the view's focused object. + /// + /// The distance to the object in world units. + /// 0 = no error, otherwise <0. + /// The distance to the object determines the translation velocity in camera mode + /// navigation modes. Generally the navigation library attempts to determine this value by + /// hit-testing the scene. There are, however, cases when the user wants to move to a far + /// off object and is not interested in what is nearby. + long GetViewFocusDistance(double &distance) const override { + (void)distance; + return navlib::make_result_code(navlib::navlib_errc::no_data_available); + } + + /// + /// Sets the camera's target position. + /// + /// The position of the camera target in world coordinates. + /// 0 = no error, otherwise <0. + /// Free cameras do not have a target. + long SetCameraTarget(const navlib::point_t &target) override { + (void)target; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + + /// + /// Sets the position of the pointer on the projection plane. + /// + /// The in world coordinates of the + /// pointer. + /// 0 = no error, otherwise <0. + long SetPointerPosition(const navlib::point_t &position) override { + (void)position; + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); + } + +protected: + std::error_code make_error_code(long result_code) const { + int errc = result_code & 0xffff; + int facility = result_code >> 16 & 0x7fff; + if (facility == FACILITY_NAVLIB) { + return std::error_code(errc, navlib_category); + } + return std::error_code(errc, std::generic_category()); + } + +protected: + bool m_enabled; + std::string m_profileHint; + std::chrono::high_resolution_clock::time_point m_frameTime; + TimingSource m_frameTimingSource; + std::shared_ptr m_pImpl; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // CNavigationModelImpl_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CNavlibImpl.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CNavlibImpl.hpp new file mode 100644 index 00000000..cfdb043e --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CNavlibImpl.hpp @@ -0,0 +1,319 @@ +#ifndef CNavlibImpl_HPP_INCLUDED +#define CNavlibImpl_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CNavlibImpl.hpp 16062 2019-04-11 12:58:50Z mbonk $ +// +// 05/25/20 MSB Fix C2280. Use std::static_pointer_cast<> instead of std::dynamic_pointer_cast<>. +// +#include +#include +#include + +// stdlib +#include +#include +#include +#include + +// navlib +#include +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// Implementation for creating a shared pointer. +/// +class CNavlibImpl : public INavlib, +#if defined(_MSC_VER) && _MSC_VER <= 1800 + public IAccessors, +#else + private IAccessors, +#endif + public std::enable_shared_from_this { + typedef CNavlibImpl this_type; + + friend std::shared_ptr + std::static_pointer_cast(const std::shared_ptr &) NOEXCEPT; + + /// + /// Make the constructors private to force creation of a shared pointer. + /// +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + CNavlibImpl() = default; +#else + CNavlibImpl() { + } +#endif + + CNavlibImpl(IAccessors *iclient) : m_iclient(iclient) { + } + +public: + /// + /// Creates a new instance of the CNavlibImpl class. + /// + /// pointer to the instance implementing the IAccessors interface. + /// true to use multi-threading, false for single-threaded. + /// true for row-major ordered matrices, false for column-major. + /// + /// A to the new CNavlibImpl instance. + /// + static std::shared_ptr + CreateInstance(IAccessors *iclient, bool multiThreaded = false, bool rowMajor = false) { + return CreateInstance(iclient, multiThreaded, + rowMajor ? navlib::row_major_order : navlib::none); + } + + /// + /// Creates a new instance of the CNavlibImpl class. + /// + /// pointer to the instance implementing the IAccessors interface. + /// true to use multi-threading, false for single-threaded. + /// A combination of the values. + /// + /// A to the new CNavlibImpl instance. + /// + static std::shared_ptr CreateInstance(IAccessors *iclient, bool multiThreaded, + navlib::nlOptions_t options) { + if (iclient == nullptr) { + throw std::logic_error("The accessor interface is null"); + } + + // So that std::make_shared<> can be used with the private constructor. + struct make_shared_enabler : public this_type { + make_shared_enabler(IAccessors *iclient) : this_type(iclient) { + } + }; + + std::shared_ptr result = std::make_shared(iclient); + result->m_pNavlib = std::unique_ptr( + new CNavlibInterface(std::static_pointer_cast(result), multiThreaded, options)); + + return result; + } + + /// + /// Clean up the resources + /// + virtual ~CNavlibImpl() { + } + + // INavlib implementation + /// + /// Close the connection to the 3D navigation library. + /// + void Close() override { + m_pNavlib->Close(); + } + + /// + /// Opens a connection to the 3D navigation library. + /// + void Open() override { + m_pNavlib->Open(); + } + + /// + /// Opens a connection to the 3D navigation library + /// + /// The name of the 3Dconnexion profile to use. + /// The connection to the library is already open. + /// Cannot create a connection to the library. + /// The name of the profile is empty. + void Open(std::string profileName) override { + m_pNavlib->Open(std::move(profileName)); + } + + /// + /// Writes the value of a property to the navlib. + /// + /// The name of the navlib property to + /// write. + /// The to write. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Write(const std::string &propertyName, const navlib::value &value) override { + return m_pNavlib->Write(propertyName, value); + } + + /// + /// Reads the value of a navlib property. + /// + /// The name of the navlib property to + /// read. + /// The to read. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long Read(const std::string &propertyName, navlib::value &value) const override { + return m_pNavlib->Read(propertyName, value); + } + + /// + /// Reads the value of a navlib string property. + /// + /// The name of the navlib property to + /// read. + /// The value of the property. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Read(const std::string &propertyName, std::string &string) const override { + return m_pNavlib->Read(propertyName, string); + } + +private: + // IEvents overrides + long SetActiveCommand(std::string commandId) override { + return m_iclient->SetActiveCommand(commandId); + } + long SetSettingsChanged(long change) override { + return m_iclient->SetSettingsChanged(change); + } + long SetKeyPress(long vkey) override { + return m_iclient->SetKeyPress(vkey); + } + long SetKeyRelease(long vkey) override { + return m_iclient->SetKeyRelease(vkey); + } + + // IHit overrides + long GetHitLookAt(navlib::point_t &position) const override { + return m_iclient->GetHitLookAt(position); + } + long SetHitAperture(double aperture) override { + return m_iclient->SetHitAperture(aperture); + } + long SetHitDirection(const navlib::vector_t &direction) override { + return m_iclient->SetHitDirection(direction); + } + long SetHitLookFrom(const navlib::point_t &eye) override { + return m_iclient->SetHitLookFrom(eye); + } + long SetHitSelectionOnly(bool onlySelection) override { + return m_iclient->SetHitSelectionOnly(onlySelection); + } + + // IModel overrides + long GetModelExtents(navlib::box_t &extents) const override { + return m_iclient->GetModelExtents(extents); + } + long GetSelectionExtents(navlib::box_t &extents) const override { + return m_iclient->GetSelectionExtents(extents); + } + long GetSelectionTransform(navlib::matrix_t &transform) const override { + return m_iclient->GetSelectionTransform(transform); + } + long GetIsSelectionEmpty(navlib::bool_t &empty) const override { + return m_iclient->GetIsSelectionEmpty(empty); + } + long SetSelectionTransform(const navlib::matrix_t &matrix) override { + return m_iclient->SetSelectionTransform(matrix); + } + long GetUnitsToMeters(double &meters) const override { + return m_iclient->GetUnitsToMeters(meters); + } + long GetFloorPlane(navlib::plane_t &floor) const override { + return m_iclient->GetFloorPlane(floor); + } + + // IPivot overrides + long GetPivotPosition(navlib::point_t &position) const override { + return m_iclient->GetPivotPosition(position); + } + long IsUserPivot(navlib::bool_t &userPivot) const override { + return m_iclient->IsUserPivot(userPivot); + } + long SetPivotPosition(const navlib::point_t &position) override { + return m_iclient->SetPivotPosition(position); + } + long GetPivotVisible(navlib::bool_t &visible) const override { + return m_iclient->GetPivotVisible(visible); + } + long SetPivotVisible(bool visible) override { + return m_iclient->SetPivotVisible(visible); + } + // ISpace3D overrides + long GetCoordinateSystem(navlib::matrix_t &matrix) const override { + return m_iclient->GetCoordinateSystem(matrix); + } + long GetFrontView(navlib::matrix_t &matrix) const override { + return m_iclient->GetFrontView(matrix); + } + // IState overrides + long SetTransaction(long transaction) override { + return m_iclient->SetTransaction(transaction); + } + long SetMotionFlag(bool motion) override { + return m_iclient->SetMotionFlag(motion); + } + // IView overrides + long GetCameraMatrix(navlib::matrix_t &matrix) const override { + return m_iclient->GetCameraMatrix(matrix); + } + long GetCameraTarget(navlib::point_t &point) const override { + return m_iclient->GetCameraTarget(point); + } + long GetPointerPosition(navlib::point_t &position) const override { + return m_iclient->GetPointerPosition(position); + } + long GetViewConstructionPlane(navlib::plane_t &plane) const override { + return m_iclient->GetViewConstructionPlane(plane); + } + long GetViewExtents(navlib::box_t &extents) const override { + return m_iclient->GetViewExtents(extents); + } + long GetViewFocusDistance(double &distance) const override { + return m_iclient->GetViewFocusDistance(distance); + } + long GetViewFOV(double &fov) const override { + return m_iclient->GetViewFOV(fov); + } + long GetViewFrustum(navlib::frustum_t &frustum) const override { + return m_iclient->GetViewFrustum(frustum); + } + long GetIsViewPerspective(navlib::bool_t &perspective) const override { + return m_iclient->GetIsViewPerspective(perspective); + } + long GetIsViewRotatable(navlib::bool_t &isRotatable) const override { + return m_iclient->GetIsViewRotatable(isRotatable); + } + long SetCameraMatrix(const navlib::matrix_t &matrix) override { + return m_iclient->SetCameraMatrix(matrix); + } + long SetCameraTarget(const navlib::point_t &target) override { + return m_iclient->SetCameraTarget(target); + } + long SetPointerPosition(const navlib::point_t &position) override { + return m_iclient->SetPointerPosition(position); + } + long SetViewExtents(const navlib::box_t &extents) override { + return m_iclient->SetViewExtents(extents); + } + long SetViewFOV(double fov) override { + return m_iclient->SetViewFOV(fov); + } + long SetViewFrustum(const navlib::frustum_t &frustum) override { + return m_iclient->SetViewFrustum(frustum); + } + +private: + IAccessors *m_iclient = nullptr; + std::unique_ptr m_pNavlib; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // CNavlibImpl_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/CNavlibInterface.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/CNavlibInterface.hpp new file mode 100644 index 00000000..a9fa06cb --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/CNavlibInterface.hpp @@ -0,0 +1,991 @@ +#ifndef CNavlibInterface_HPP_INCLUDED +#define CNavlibInterface_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: CNavlibInterface.hpp 16051 2019-04-09 11:29:53Z mbonk $ +// +// 07/23/19 MSB Do not set the cookie to zero when the open fails. +// +#include +#include +#include +#include + +// stdlib +#include +#include +#include +#include +#include + +// navlib +#include +#include +#include + +#if defined(WAMP_CLIENT) && (WAMP_CLIENT==1) +// wamp +#include +#include +#endif + + +namespace TDx { +namespace SpaceMouse { +/// +/// Template to get a specific interface from a unique pointer. +/// +template Ty_ *GetInterface(const std::unique_ptr < I_>& p) { + I_ *i = p.get(); + if (i == nullptr) { + return nullptr; + } + + Ty_ *t = static_cast(*p.get()); + return t; +} + +/// +/// The base class for the Accessors items. +/// +/// The purpose of the class is to use polymorphism to avoid dynamic casts. +/// +class AccessorInterface { +public: + explicit operator Navigation3D::ISpace3D *() { + return GetISpace3DInterface(); + } + explicit operator Navigation3D::IView *() { + return GetIViewInterface(); + } + explicit operator Navigation3D::IModel *() { + return GetIModelInterface(); + } + explicit operator Navigation3D::IPivot *() { + return GetIPivotInterface(); + } + explicit operator Navigation3D::IHit *() { + return GetIHitInterface(); + } + explicit operator Navigation3D::IEvents *() { + return GetIEventsInterface(); + } + explicit operator Navigation3D::IState *() { + return GetIStateInterface(); + } + +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + AccessorInterface() = default; + virtual ~AccessorInterface() = default; + AccessorInterface(const AccessorInterface &) = delete; + AccessorInterface &operator=(const AccessorInterface &) = delete; +#else + AccessorInterface(){}; + virtual ~AccessorInterface(){}; +private: + AccessorInterface(const AccessorInterface &); + AccessorInterface &operator=(const AccessorInterface &); +#endif + +protected: + virtual Navigation3D::ISpace3D *GetISpace3DInterface() { + return nullptr; + } + virtual Navigation3D::IView *GetIViewInterface() { + return nullptr; + } + virtual Navigation3D::IModel *GetIModelInterface() { + return nullptr; + } + virtual Navigation3D::IPivot *GetIPivotInterface() { + return nullptr; + } + virtual Navigation3D::IHit *GetIHitInterface() { + return nullptr; + } + virtual Navigation3D::IEvents *GetIEventsInterface() { + return nullptr; + } + virtual Navigation3D::IState *GetIStateInterface() { + return nullptr; + } +}; + + +class IWeakPtr { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IWeakPtr() = default; +#else + virtual ~IWeakPtr() = 0 { + } +#endif + virtual std::unique_ptr lock() = 0; +}; + + +// General template for a . +template class WeakAccessorPtr : public IWeakPtr { +public: + std::unique_ptr lock() override { + return std::unique_ptr(); + } +}; + + +/// +/// Specialization of the template for the interface. +/// +template <> class WeakAccessorPtr : public IWeakPtr { + // Implementation of the accessors interfaces. + class Accessors : public AccessorInterface { + public: + Accessors(std::shared_ptr accessors) + : m_interface(std::forward>(accessors)) { + } + + protected: + Navigation3D::ISpace3D *GetISpace3DInterface() override { + return static_cast(m_interface.get()); + } + Navigation3D::IView *GetIViewInterface() override { + return static_cast(m_interface.get()); + } + Navigation3D::IModel *GetIModelInterface() override { + return static_cast(m_interface.get()); + } + Navigation3D::IPivot *GetIPivotInterface() override { + return static_cast(m_interface.get()); + } + Navigation3D::IHit *GetIHitInterface() override { + return static_cast(m_interface.get()); + } + Navigation3D::IEvents *GetIEventsInterface() override { + return static_cast(m_interface.get()); + } + Navigation3D::IState *GetIStateInterface() override { + return static_cast(m_interface.get()); + } + + private: + std::shared_ptr m_interface; + }; + +public: + WeakAccessorPtr(std::shared_ptr &&accessors) + : m_interface(std::forward>(accessors)) { + } + + std::unique_ptr lock() override { + return std::unique_ptr(new Accessors(m_interface.lock())); + } + +protected: + std::weak_ptr m_interface; +}; + +/// +/// Specialization of the template for the interface. +/// +template <> class WeakAccessorPtr : public IWeakPtr { + // Implementation of the accessors interfaces. + class Accessors : public AccessorInterface { + public: + Accessors(std::shared_ptr accessors) + : m_interface(std::forward>(accessors)) { + } + + protected: + Navigation3D::IEvents *GetIEventsInterface() override { + return static_cast(m_interface.get()); + } + + private: + std::shared_ptr m_interface; + }; + +public: + WeakAccessorPtr(std::shared_ptr &&accessors) + : m_interface(std::forward>(accessors)) { + } + + std::unique_ptr lock() override { + return std::unique_ptr(new Accessors(m_interface.lock())); + } + +protected: + std::weak_ptr m_interface; +}; + +/// +/// Template to allow defining the static members in the header file +/// +template struct StaticSinkCollection { +protected: + static CCookieCollection s_sinkCollection; + static std::mutex s_mutex; +}; + +template +CCookieCollection StaticSinkCollection::s_sinkCollection; + +/// +/// Mutex used to synchronize the trace output. +/// +template std::mutex StaticSinkCollection::s_mutex; + +namespace Navigation3D { +/// +/// Class implements the interface to the navlib. +/// +class CNavlibInterface : public INavlib, + private StaticSinkCollection { +public: + /// + /// Initializes a new instance of the CNavlibInterface class. + /// + /// Shared pointer to the instance implementing the IAccessors interface + /// accessors and mutators. + /// true to use multi-threading, false for single-threaded. + /// true for row-major ordered matrices, false for column-major. + template + explicit CNavlibInterface(std::shared_ptr sink, bool multiThreaded = false, + bool rowMajor = false) + : m_hdl(INVALID_NAVLIB_HANDLE), + m_cookie(s_sinkCollection.insert(std::make_shared>(std::move(sink)))) +#if defined(_MSC_VER) && (_MSC_VER < 1800) + { + navlib::nlCreateOptions_t options = {sizeof(navlib::nlCreateOptions_t), multiThreaded, + rowMajor ? navlib::row_major_order : navlib::none}; + + m_createOptions = options; + } +#else + , + m_createOptions{sizeof(navlib::nlCreateOptions_t), multiThreaded, + rowMajor ? navlib::row_major_order : navlib::none} { + } +#endif + + + /// + /// Initializes a new instance of the CNavlibInterface class. + /// + /// Shared pointer to the instance implementing the IAccessors interface + /// accessors and mutators. + /// true to use multi-threading, false for single-threaded. + /// A combination of the values. + template + explicit CNavlibInterface(std::shared_ptr sink, bool multiThreaded, + navlib::nlOptions_t options) + : m_hdl(INVALID_NAVLIB_HANDLE), + m_cookie(s_sinkCollection.insert(std::make_shared>(std::move(sink)))) +#if defined(_MSC_VER) && (_MSC_VER < 1800) + { + navlib::nlCreateOptions_t createOptions = {sizeof(navlib::nlCreateOptions_t), multiThreaded, + options}; + + m_createOptions = createOptions; + } +#else + , + m_createOptions({sizeof(navlib::nlCreateOptions_t), multiThreaded, options}) { + } +#endif + + /// + /// Clean up the resources + /// + ~CNavlibInterface() override { + using namespace ::navlib; + if (m_cookie) { + s_sinkCollection.erase(m_cookie); + } + if (m_hdl != INVALID_NAVLIB_HANDLE) { + NlClose(m_hdl); + } + } + +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + CNavlibInterface(const CNavlibInterface &) = delete; + CNavlibInterface& operator=(const CNavlibInterface &) = delete; + #else +private: + CNavlibInterface(const CNavlibInterface &); + CNavlibInterface &operator=(const CNavlibInterface &); +#endif + +public : + /// + /// Close the connection to the 3D navigation library. + /// + void Close() override { + using namespace ::navlib; + if (m_hdl != INVALID_NAVLIB_HANDLE) { + std::unique_lock lock(m_mutex); + if (m_hdl != INVALID_NAVLIB_HANDLE) { + NlClose(m_hdl); + m_hdl = INVALID_NAVLIB_HANDLE; + } + } + } + + /// + /// Opens a connection to the 3D navigation library. + /// + void Open() override { + Open(m_name); + } + + /// + /// Opens a connection to the 3D navigation library + /// + /// The text to display in the 3Dconnexion profile. + /// The connection to the library is already open. + /// Cannot create a connection to the library. + /// The text for the profile is empty. + void Open(std::string profileText) override { + using namespace ::navlib; + + if (profileText.empty()) { + throw std::invalid_argument("The text for the profile is empty."); + } + + std::unique_lock lock(m_mutex); + + if (m_hdl != INVALID_NAVLIB_HANDLE) { + throw std::system_error(navlib::make_error_code(navlib_errc::already_connected), + "Connection to the library is already open."); + } + +#if defined(WAMP_CLIENT) && (WAMP_CLIENT == 1) + if (!m_session) { + // The SSL context is required, and holds certificates + ssl::context ctx{ssl::context::tlsv12_client}; + + m_session = std::make_shared(ctx); + } + if (!m_session->is_running()) { + std::error_code ec; + m_session->run(ec); + if (ec) { + throw std::system_error(ec, "Cannot run navlib session."); + } + } +#endif + + auto isink = s_sinkCollection.at(m_cookie)->lock(); + std::vector accessors; + // Event accessors + if (nullptr != GetInterface(isink)) { + accessors.insert( + accessors.end(), + {{commands_activeCommand_k, nullptr, &CNavlibInterface::SetActiveCommand, m_cookie}, + {events_keyPress_k, nullptr, &CNavlibInterface::SetKeyPress, m_cookie}, + {events_keyRelease_k, nullptr, &CNavlibInterface::SetKeyRelease, m_cookie}, + {settings_changed_k, nullptr, &CNavlibInterface::SetSettingsChanged, m_cookie}}); + } + + // 3D space accessors + if (nullptr != GetInterface(isink)) { + accessors.insert( + accessors.end(), + {{coordinate_system_k, &CNavlibInterface::GetCoordinateSystem, nullptr, m_cookie}, + {views_front_k, &CNavlibInterface::GetFrontView, nullptr, m_cookie}}); + } + + // state accessors + if (nullptr != GetInterface(isink)) { + accessors.insert( + accessors.end(), + {{motion_k, nullptr, &CNavlibInterface::SetMotionFlag, m_cookie}, + {transaction_k, nullptr, &CNavlibInterface::SetTransaction, m_cookie}}); + } + + // view access + if (nullptr != GetInterface(isink)) { + accessors.insert(accessors.end(), + {{view_affine_k, &CNavlibInterface::GetCameraMatrix, &CNavlibInterface::SetCameraMatrix, + m_cookie}, + {view_constructionPlane_k, &CNavlibInterface::GetViewConstructionPlane, nullptr, + m_cookie}, + {view_extents_k, &CNavlibInterface::GetViewExtents, &CNavlibInterface::SetViewExtents, + m_cookie}, + {view_focusDistance_k, &CNavlibInterface::GetViewFocusDistance, nullptr, m_cookie}, + {view_fov_k, &CNavlibInterface::GetViewFOV, &CNavlibInterface::SetViewFOV, m_cookie}, + {view_frustum_k, &CNavlibInterface::GetViewFrustum, &CNavlibInterface::SetViewFrustum, + m_cookie}, + {view_perspective_k, &CNavlibInterface::GetIsViewPerspective, nullptr, m_cookie}, + {view_target_k, &CNavlibInterface::GetCameraTarget, &CNavlibInterface::SetCameraTarget, + m_cookie}, + {view_rotatable_k, &CNavlibInterface::GetIsViewRotatable, nullptr, m_cookie}, + {pointer_position_k, &CNavlibInterface::GetPointerPosition, + &CNavlibInterface::SetPointerPosition, m_cookie}}); + } + + // pivot accessors + if (nullptr != GetInterface(isink)) { + accessors.insert( + accessors.end(), + {{pivot_position_k, &CNavlibInterface::GetPivotPosition, &CNavlibInterface::SetPivotPosition, m_cookie}, + {pivot_user_k, &CNavlibInterface::IsUserPivot, nullptr, m_cookie}, + {pivot_visible_k, &CNavlibInterface::GetPivotVisible, &CNavlibInterface::SetPivotVisible, m_cookie}}); + } + + // hit testing for auto pivot algorithm etc. + if (nullptr != GetInterface(isink)) { + accessors.insert(accessors.end(), + {{hit_lookfrom_k, nullptr, &CNavlibInterface::SetHitLookFrom, m_cookie}, + {hit_direction_k, nullptr, &CNavlibInterface::SetHitDirection, m_cookie}, + {hit_aperture_k, nullptr, &CNavlibInterface::SetHitAperture, m_cookie}, + {hit_lookat_k, &CNavlibInterface::GetHitLookAt, nullptr, m_cookie}, + {hit_selectionOnly_k, nullptr, &CNavlibInterface::SetHitSelectionOnly, m_cookie}}); + } + + // model access + if (nullptr != GetInterface(isink)) { + accessors.insert(accessors.end(), + {{model_extents_k, &CNavlibInterface::GetModelExtents, nullptr, m_cookie}, + {selection_empty_k, &CNavlibInterface::GetIsSelectionEmpty, nullptr, m_cookie}, + {selection_extents_k, &CNavlibInterface::GetSelectionExtents, nullptr, m_cookie}, + {selection_affine_k, &CNavlibInterface::GetSelectionTransform, + &CNavlibInterface::SetSelectionTransform, m_cookie}, + {model_unitsToMeters_k, &CNavlibInterface::GetUnitsToMeters, nullptr, m_cookie}, + {model_floorPlane_k, &CNavlibInterface::GetFloorPlane, nullptr, m_cookie}}); + } + + // Create the navlib instance + long error = NlCreate(&m_hdl, profileText.c_str(), accessors.data(), + accessors.size(), &m_createOptions); + + if (error != 0) { + throw std::system_error( + navlib::make_error_code(static_cast(error & 0xffff)), + "Cannot create a connection to the 3DMouse."); + } + + m_name = std::move(profileText); + } + + /// + /// Writes the value of a property to the navlib. + /// + /// The name of the navlib property to + /// write. + /// The to write. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Write(const std::string &propertyName, const navlib::value &value) override { + if (m_hdl == INVALID_NAVLIB_HANDLE) { + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); + } + + long resultCode = WriteValue(m_hdl, propertyName.c_str(), &value); + + return resultCode; + } + + /// + /// Reads the value of a navlib property. + /// + /// The name of the navlib property to + /// read. + /// The to read. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Read(const std::string &propertyName, navlib::value &value) const override { + if (m_hdl == INVALID_NAVLIB_HANDLE) { + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); + } + + long resultCode = ReadValue(m_hdl, propertyName.c_str(), &value); + + return resultCode; + } + + /// + /// Reads the value of a navlib string property. + /// + /// The name of the navlib property to + /// read. + /// The value of the property. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + long Read(const std::string &propertyName, std::string &string) const override { + if (m_hdl == INVALID_NAVLIB_HANDLE) { + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); + } + + navlib::value value(&string[0], string.length()); + long resultCode = ReadValue(m_hdl, propertyName.c_str(), &value); + if ((resultCode & 0xffff) == static_cast(navlib::navlib_errc::insufficient_buffer)) { + string.resize(value.string.length); + value = navlib::value(&string[0], string.length()); + resultCode = ReadValue(m_hdl, propertyName.c_str(), &value); + } + + if (resultCode == 0) { + string.resize(value.string.length); + } + + return resultCode; + } + +private: + typedef std::unique_ptr isink_t; + + template + static long GetValue(navlib::param_t cookie, navlib::property_t property, navlib::value_t *value, + F fn) { + try { + isink_t isink = s_sinkCollection.at(cookie)->lock(); + long result = fn(std::move(isink)); +#if defined(_DEBUG) && defined(TRACE_NAVLIB) + std::unique_lock lock(s_mutex); + std::clog << "GetValue(0x" << std::hex << cookie << std::dec << ", " << property << ", " + << *value << ") result =0x" << std::hex << result << std::endl; +#endif + return result; + } + catch (const std::out_of_range &e) { + std::unique_lock lock(s_mutex); + std::cerr << "std::out_of_range exception thrown in GetValue(0x" << std::hex << cookie + << std::dec << ", " << property << ", value)\n" + << *value << e.what() << std::endl; + return navlib::make_result_code(navlib::navlib_errc::invalid_argument); + } catch (const std::exception &e) { + std::cerr << "Uncaught exception thrown in GetValue(0x" << std::hex << cookie << std::dec + << ", " << property << ", value)\n" + << *value << e.what() << std::endl; + } + return navlib::make_result_code(navlib::navlib_errc::error); + } + + template + static long SetValue(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value, F fn) { + try { + isink_t isink = s_sinkCollection.at(cookie)->lock(); + long result = fn(std::move(isink)); +#if defined(_DEBUG) && defined(TRACE_NAVLIB) + std::clog << "SetValue(0x" << std::hex << cookie << std::dec << ", " << property << ", " + << *value << ") result =0x" << std::hex << result << std::endl; +#endif + return result; + } + catch (const std::out_of_range &e) { + std::unique_lock lock(s_mutex); + std::cerr << "std::out_of_range exception thrown in SetValue(0x" << std::hex << cookie + << std::dec << ", " << property << ", value)\n" + << *value << e.what() << std::endl; + return navlib::make_result_code(navlib::navlib_errc::invalid_argument); + } catch (const std::exception &e) { + std::unique_lock lock(s_mutex); + std::cerr << "Uncaught exception thrown in SetValue(0x" << std::hex << cookie << std::dec + << ", " << property << "," << *value << ")\n" + << e.what() << std::endl; + } + return navlib::make_result_code(navlib::navlib_errc::error); + } + + /// + /// IEvents accessors and mutators + /// + static long SetActiveCommand(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetActiveCommand(static_cast(*value)); + }); + } + + static long SetSettingsChanged(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetSettingsChanged(*value); + }); + } + + static long SetKeyPress(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetKeyPress(*value); + }); + } + static long SetKeyRelease(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetKeyRelease(*value); + }); + } + + /// + /// IHit accessors and mutators + /// + static long GetHitLookAt(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetHitLookAt(*value); + }); + } + static long SetHitAperture(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetHitAperture(*value); + }); + } + static long SetHitDirection(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetHitDirection(*value); + }); + } + static long SetHitLookFrom(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetHitLookFrom(*value); + }); + } + static long SetHitSelectionOnly(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetHitSelectionOnly(*value); + }); + } + + /// + /// IModel accessors and mutators + /// + static long GetModelExtents(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetModelExtents(*value); + }); + } + static long GetSelectionExtents(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetSelectionExtents(*value); + }); + } + static long GetSelectionTransform(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetSelectionTransform(*value); + }); + } + static long GetIsSelectionEmpty(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetIsSelectionEmpty(*value); + }); + } + static long SetSelectionTransform(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetSelectionTransform(*value); + }); + } + static long GetUnitsToMeters(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetUnitsToMeters(*value); + }); + } + static long GetFloorPlane(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetFloorPlane(*value); + }); + } + + /// + /// IPivot accessors and mutators + /// + static long GetPivotPosition(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetPivotPosition(*value); + }); + } + static long IsUserPivot(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->IsUserPivot(*value); + }); + } + static long SetPivotPosition(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetPivotPosition(*value); + }); + } + static long GetPivotVisible(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetPivotVisible(*value); + }); + } + static long SetPivotVisible(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetPivotVisible(*value); + }); + } + + /// + /// ISpace3D accessors and mutators + /// + static long GetCoordinateSystem(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetCoordinateSystem(*value); + }); + } + static long GetFrontView(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetFrontView(*value); + }); + } + + /// + /// IState accessors and mutators + /// + static long SetTransaction(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetTransaction(*value); + }); + } + static long SetMotionFlag(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetMotionFlag(*value); + }); + } + + /// + /// IView accessors and mutators + /// + static long GetCameraMatrix(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetCameraMatrix(*value); + }); + } + static long GetCameraTarget(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetCameraTarget(*value); + }); + } + static long GetPointerPosition(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetPointerPosition(*value); + }); + } + static long GetViewConstructionPlane(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetViewConstructionPlane(*value); + }); + } + static long GetViewExtents(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetViewExtents(*value); + }); + } + static long GetViewFOV(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, + [&](isink_t isink) { return GetInterface(isink)->GetViewFOV(*value); }); + } + static long GetViewFrustum(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetViewFrustum(*value); + }); + } + static long GetIsViewPerspective(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetIsViewPerspective(*value); + }); + } + static long GetIsViewRotatable(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetIsViewRotatable(*value); + }); + } + static long GetViewFocusDistance(navlib::param_t cookie, navlib::property_t property, + navlib::value_t *value) { + return GetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->GetViewFocusDistance(*value); + }); + } + static long SetCameraMatrix(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetCameraMatrix(*value); + }); + } + static long SetCameraTarget(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetCameraTarget(*value); + }); + } + static long SetPointerPosition(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetPointerPosition(*value); + }); + } + static long SetViewExtents(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetViewExtents(*value); + }); + } + static long SetViewFOV(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, + [&](isink_t isink) { return GetInterface(isink)->SetViewFOV(*value); }); + } + static long SetViewFrustum(navlib::param_t cookie, navlib::property_t property, + const navlib::value_t *value) { + return SetValue(cookie, property, value, [&](isink_t isink) { + return GetInterface(isink)->SetViewFrustum(*value); + }); + } + +private: + /// + /// Read a value from the navlib. + /// + /// The to the navigation library returned by + /// a previous call to . + /// The name of the navlib property to read. + /// Pointer to a to receive the value. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long ReadValue(navlib::nlHandle_t nh, navlib::property_t name, navlib::value_t *value) const { + using namespace ::navlib; + try { + long resultCode = NlReadValue(nh, name, value); +#if defined(_DEBUG) && defined(TRACE_NAVLIB) + std::unique_lock lock(s_mutex); + std::clog << "NlReadValue(0x" << std::hex << nh << std::dec << ", " << name << ", " << *value + << ") result =0x" << std::hex << resultCode << std::endl; +#endif + return resultCode; + } + catch (const std::exception &e) { + std::unique_lock lock(s_mutex); + std::cerr << "exception thrown in NlReadValue(0x" << std::hex << nh << std::dec + << ", " << name << ", value)\n" + << *value << " " << e.what() << std::endl; + } + return navlib::make_result_code(navlib::navlib_errc::error); + } + + /// + /// Write a value to the navlib. + /// + /// The to the navigation library returned by + /// a previous call to . + /// The name of the navlib property to read. + /// Pointer to a to receive the value. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + long WriteValue(navlib::nlHandle_t nh, navlib::property_t name, + const navlib::value_t *value) { + using namespace ::navlib; + try { + long resultCode = NlWriteValue(nh, name, value); +#if defined(_DEBUG) && defined(TRACE_NAVLIB) + std::unique_lock lock(s_mutex); + std::clog << "NlWriteValue(0x" << std::hex << nh << std::dec << ", " << name << ", " << *value + << ") result =0x" << std::hex << resultCode << std::endl; +#endif + return resultCode; + } + catch (const std::exception &e) { + std::unique_lock lock(s_mutex); + std::cerr << "exception thrown in NlWriteValue(0x" << std::hex << nh << std::dec + << ", " << name << ", value)\n" + << *value << " " << e.what() << std::endl; + } + return navlib::make_result_code(navlib::navlib_errc::error); + } + +#if defined(WAMP_CLIENT) && (WAMP_CLIENT == 1) +private: + long NlCreate(navlib::nlHandle_t* nh, const char *appname, + const navlib::accessor_t property_accessors[], size_t accessor_count, + const navlib::nlCreateOptions_t *options) { + if (nh == nullptr) { + return navlib::make_result_code(navlib::navlib_errc::invalid_argument); + } + return m_session->NlCreate(*nh, appname, property_accessors, accessor_count, options); + } + + long NlClose(navlib::nlHandle_t nh) { + return m_session->NlClose(nh); + } + + long NlReadValue(navlib::nlHandle_t nh, navlib::property_t name, navlib::value_t *value) const { + if (value == nullptr) { + return navlib::make_result_code(navlib::navlib_errc::invalid_argument); + } + + if (!m_session->is_running()) { + throw std::system_error(navlib::make_error_code(navlib::navlib_errc::invalid_operation), + "No active NL-Session."); + } + + return m_session->NlReadValue(nh, name, *value); + } + + long NlWriteValue(navlib::nlHandle_t nh, navlib::property_t name, + const navlib::value_t *value) { + if (value == nullptr) { + return navlib::make_result_code(navlib::navlib_errc::invalid_argument); + } + + if (!m_session->is_running()) { + throw std::system_error(navlib::make_error_code(navlib::navlib_errc::invalid_operation), + "No active NL-Session."); + } + + return m_session->NlWriteValue(nh, name, *value); + } + + mutable std::shared_ptr m_session; +#endif + +private: + navlib::nlHandle_t m_hdl; + std::mutex m_mutex; + navlib::param_t m_cookie; + std::string m_name; + navlib::nlCreateOptions_t m_createOptions; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // CNavigationModelImpl_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IAccessors.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IAccessors.hpp new file mode 100644 index 00000000..b2201d81 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IAccessors.hpp @@ -0,0 +1,44 @@ +#ifndef IAccessors_HPP_INCLUDED +#define IAccessors_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IAccessors.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// + +#include +#include +#include +#include +#include +#include +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// The accessor interface to the client 3D properties. +/// +class IAccessors : public ISpace3D, + public IView, + public IModel, + public IPivot, + public IHit, + public IEvents, + public IState {}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IAccessors_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IActionAccessors.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IActionAccessors.hpp new file mode 100644 index 00000000..90ce4f56 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IActionAccessors.hpp @@ -0,0 +1,33 @@ +#ifndef IActionAccessors_HPP_INCLUDED +#define IActionAccessors_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id$ +// +// + +#include + +namespace TDx { +namespace SpaceMouse { +namespace ActionInput { +/// +/// The accessor interface to the client action input properties. +/// +class IActionAccessors : public Navigation3D::IEvents { +}; +} // namespace ActionInput +} // namespace SpaceMouse +} // namespace TDx +#endif // IActionAccessors_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IEvents.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IEvents.hpp new file mode 100644 index 00000000..b8a32f26 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IEvents.hpp @@ -0,0 +1,74 @@ +#ifndef IEvents_HPP_INCLUDED +#define IEvents_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IEvents.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// + +// navlib +#include + +//stdlib +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// The Events interface +/// +class IEvents { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IEvents() = default; +#else + virtual ~IEvents() = 0 { + } +#endif + + /// + /// Is called when the user invokes an application command from the SpaceMouse. + /// + /// The id of the command to invoke. + /// The result of the function: 0 = no error, otherwise <0. + virtual long SetActiveCommand(std::string commandId) = 0; + + /// + /// Is called when the navigation settings change. + /// + /// The change count. + /// 0 = no error, otherwise <0. + virtual long SetSettingsChanged(long count) = 0; + + /// + /// Is invoked when the user releases a key on the 3D Mouse, which has been programmed to send a + /// virtual key code. + /// + /// The virtual key code of the key pressed. + /// 0 = no error, otherwise <0. + virtual long SetKeyPress(long vkey) = 0; + + /// + /// Is invoked when the user releases a key on the 3D Mouse, which has been programmed to send a + /// virtual key code. + /// + /// The virtual key code of the key released. + /// 0 = no error, otherwise <0. + virtual long SetKeyRelease(long vkey) = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IEvents_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IHit.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IHit.hpp new file mode 100644 index 00000000..780140e9 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IHit.hpp @@ -0,0 +1,74 @@ +#ifndef IHit_HPP_INCLUDED +#define IHit_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IHit.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// The hit-testing interface. +/// +class IHit { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IHit() = default; +#else + virtual ~IHit() = 0 { + } +#endif + + /// + /// Is called when the navigation library queries the result of the hit-testing. + /// + /// The hit in world coordinates. + /// 0 =no error, otherwise <0 . + virtual long GetHitLookAt(navlib::point_t &position) const = 0; + + /// + /// Is called when the navigation library sets the aperture of the hit-testing ray/cone. + /// + /// The aperture of the ray/cone on the near plane. + /// 0 =no error, otherwise <0 . + virtual long SetHitAperture(double aperture) = 0; + + /// + /// Is called when the navigation library sets the direction of the hit-testing ray/cone. + /// + /// The direction of the ray/cone. + /// 0 =no error, otherwise <0 . + virtual long SetHitDirection(const navlib::vector_t& direction) = 0; + + /// + /// Is called when the navigation library sets the source of the hit-testing ray/cone. + /// + /// The source of the hit cone. + /// 0 =no error, otherwise <0 . + virtual long SetHitLookFrom(const navlib::point_t& eye) = 0; + + /// + /// Is called when the navigation library sets the selection filter for hit-testing. + /// + /// true = ignore non-selected items. + /// 0 =no error, otherwise <0 . + virtual long SetHitSelectionOnly(bool onlySelection) = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IHit_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IModel.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IModel.hpp new file mode 100644 index 00000000..d24faf41 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IModel.hpp @@ -0,0 +1,102 @@ +#ifndef IModel_HPP_INCLUDED +#define IModel_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IModel.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// The Model interface +/// +class IModel { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IModel() = default; +#else + virtual ~IModel() = 0 { + } +#endif + + /// + /// Is called when the navigation library needs to get the extents of the model. + /// + /// A representing the extents of the + /// model. + /// 0 = no error, otherwise <0. + virtual long GetModelExtents(navlib::box_t &extents) const = 0; + + /// + /// Is called when the navigation library needs to get the extents of the selection. + /// + /// A representing the extents of the + /// selection. + /// 0 = no error, otherwise <0. + virtual long GetSelectionExtents(navlib::box_t &extents) const = 0; + + /// + /// Is called to get the selections's transform . + /// + /// The world affine of the + /// selection. + /// 0 = no error, otherwise <0. + virtual long GetSelectionTransform(navlib::matrix_t &transform) const = 0; + + /// + /// Is called to query if the selection is empty. + /// + /// true if nothing is selected. + /// 0 = no error, otherwise <0. + virtual long GetIsSelectionEmpty(navlib::bool_t &empty) const = 0; + + /// + /// Is called to set the selections's transform . + /// + /// The world affine of the selection. + /// 0 = no error, otherwise <0. + virtual long SetSelectionTransform(const navlib::matrix_t& matrix) = 0; + + /// + /// Is called to retrieve the length of the model/world units in meters. + /// + /// The length of a model/world unit in meters. + /// 0 = no error, otherwise <0. + /// + /// The conversion factor is used by the Navigation Library to calculate the height above + /// the floor in walk mode and the speed in the first-person motion model. + /// The Navigation Library assumes that this value does not change and it is only queried + /// once. + /// + virtual long GetUnitsToMeters(double &meters) const = 0; + + /// + /// Is called to retrieve the plane equation of the floor. + /// + /// The plane equation of the floor plane. + /// 0 = no error, otherwise <0. + /// + /// The plane equation is used by the Navigation Library to determine the floor for the + /// walk navigation mode, where the height of the eye is fixed to 1.5m above the floor plane. + /// The floor need not be parallel to the world ground plane. + /// + virtual long GetFloorPlane(navlib::plane_t &floor) const = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IModel_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/INavlib.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/INavlib.hpp new file mode 100644 index 00000000..9e5d2f6c --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/INavlib.hpp @@ -0,0 +1,98 @@ +#ifndef INavlib_HPP_INCLUDED +#define INavlib_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: INavlib.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +// stdlib +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// The interface to access the navigation library properties. +/// +class INavlibProperty { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~INavlibProperty() = default; +#else + virtual ~INavlibProperty() = 0 { + } +#endif + + /// + /// Writes the value of a property to the navlib. + /// + /// The name of the navlib property to + /// write. + /// The to write. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + virtual long Write(const std::string &propertyName, const navlib::value &value) = 0; + + /// + /// Reads the value of a navlib property. + /// + /// The name of the navlib property to + /// read. + /// The to read. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib / 3D Mouse. + virtual long Read(const std::string &propertyName, navlib::value &value) const = 0; + + /// + /// Reads the value of a navlib string property. + /// + /// The name of the navlib property to + /// read. + /// The value of the property. + /// 0 =no error, otherwise a value from . + /// No connection to the navlib. + virtual long Read(const std::string &propertyName, std::string &string) const = 0; +}; + +/// +/// The interface to access the navigation library. +/// +class INavlib : public INavlibProperty { +public: + /// + /// Close the connection to the 3D navigation library. + /// + virtual void Close() = 0; + + /// + /// Opens a connection to the 3D navigation library. + /// + virtual void Open() = 0; + + /// + /// Opens a connection to the 3D navigation library + /// + /// The name of the 3Dconnexion profile to use. + /// The connection to the library is already open. + /// Cannot create a connection to the library. + /// The name of the profile is empty. + virtual void Open(std::string profileName) = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // INavlib_HPP_INCLUDED + diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IPivot.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IPivot.hpp new file mode 100644 index 00000000..a7a25600 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IPivot.hpp @@ -0,0 +1,74 @@ +#ifndef IPivot_HPP_INCLUDED +#define IPivot_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IPivot.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { + /// + /// The interface to access the pivot. + /// +class IPivot { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IPivot() = default; +#else + virtual ~IPivot() = 0 { + } +#endif + + /// + /// Gets the position of the rotation pivot. + /// + /// The pivot in world coordinates. + /// 0 = no error, otherwise <0. + virtual long GetPivotPosition(navlib::point_t &position) const = 0; + + /// + /// Queries if the user has manually set a pivot point. + /// + /// true if the user has set a pivot otherwise false. + /// 0 = no error, otherwise <0. + virtual long IsUserPivot(navlib::bool_t &userPivot) const = 0; + + /// + /// Sets the position of the rotation pivot. + /// + /// The pivot in world coordinates. + /// 0 = no error, otherwise <0. + virtual long SetPivotPosition(const navlib::point_t& position) = 0; + + /// + /// Queries the visibility of the pivot image. + /// + /// true if the pivot is visible otherwise false. + /// 0 = no error, otherwise <0. + virtual long GetPivotVisible(navlib::bool_t &visible) const = 0; + + /// + /// Sets the visibility of the pivot image. + /// + /// true if the pivot is visible otherwise false. + /// 0 = no error, otherwise <0. + virtual long SetPivotVisible(bool visible) = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IPivot_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/ISpace3D.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/ISpace3D.hpp new file mode 100644 index 00000000..36c4e0c2 --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/ISpace3D.hpp @@ -0,0 +1,55 @@ +#ifndef ISpace3D_HPP_INCLUDED +#define ISpace3D_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: ISpace3D.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// The interface to access the client coordinate system. +/// +class ISpace3D { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~ISpace3D() = default; +#else + virtual ~ISpace3D() = 0 { + } +#endif + + /// + /// Gets the coordinate system used by the client. + /// + /// The coordinate system . + /// 0 = no error, otherwise <0. + /// The matrix describes the applications coordinate frame in the navlib coordinate + /// system. i.e. the application to navlib transform. + virtual long GetCoordinateSystem(navlib::matrix_t &matrix) const = 0; + + /// + /// Gets the orientation of the front view. + /// + /// The front view transform . + /// 0 = no error, otherwise <0. + virtual long GetFrontView(navlib::matrix_t &matrix) const = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // ISpace3D_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IState.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IState.hpp new file mode 100644 index 00000000..0ef976bb --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IState.hpp @@ -0,0 +1,54 @@ +#ifndef IState_HPP_INCLUDED +#define IState_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IState.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { + /// + /// Interface to access the navigation state. + /// +class IState { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IState() = default; +#else + virtual ~IState() = 0 { + } +#endif + + /// + /// Is called when the navigation library starts or stops a navigation transaction. + /// + /// The transaction number: >0 begin, ==0 end. + /// 0 = no error, otherwise <0. + virtual long SetTransaction(long transaction) = 0; + + /// + /// Is called when the navigation instance starts or stops a sequence of motion frames. + /// + /// The motion flag: true = start, false = end. + /// 0 = no error, otherwise <0. + /// This can be used to start an animation loop. + virtual long SetMotionFlag(bool motion) = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IState_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/SpaceMouse/IView.hpp b/thirdparty/3DConnexion/inc/SpaceMouse/IView.hpp new file mode 100644 index 00000000..7cb64dbf --- /dev/null +++ b/thirdparty/3DConnexion/inc/SpaceMouse/IView.hpp @@ -0,0 +1,156 @@ +#ifndef IView_HPP_INCLUDED +#define IView_HPP_INCLUDED +// +// ------------------------------------------------------------------------------------------------ +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------ +// +// +// ************************************************************************************************ +// File History +// +// $Id: IView.hpp 16047 2019-04-05 12:51:24Z mbonk $ +// +// +#include + +namespace TDx { +namespace SpaceMouse { +namespace Navigation3D { +/// +/// View callback interface. +/// +class IView { +public: +#if !defined(_MSC_VER) || (_MSC_VER > 1700) + virtual ~IView() = default; +#else + virtual ~IView() = 0 { + } +#endif + + /// + /// Gets the camera matrix of the view. + /// + /// The camera/view . + /// 0 = no error, otherwise <0. + virtual long GetCameraMatrix(navlib::matrix_t &matrix) const = 0; + + /// + /// Gets the camera's target point. + /// + /// The position of the camera target in world coordinates. + /// 0 = no error, otherwise <0. + /// Free cameras do not have a target. + virtual long GetCameraTarget(navlib::point_t &target) const = 0; + + /// + /// Gets the position of the pointer on the near clipping plane. + /// + /// The in world coordinates of the + /// pointer. 0 = no error, otherwise <0. + virtual long GetPointerPosition(navlib::point_t &position) const = 0; + + /// + /// Gets the view's construction plane. + /// + /// The plane equation of the construction plane. + /// 0 = no error, otherwise <0. + virtual long GetViewConstructionPlane(navlib::plane_t &plane) const = 0; + + /// + /// Gets the extents of the view. + /// + /// A representing the extents of the + /// view. + /// 0 = no error, otherwise <0. + virtual long GetViewExtents(navlib::box_t &extents) const = 0; + + /// + /// Gets the camera's/view's distance to the focused object. + /// + /// The distance in world units. + /// 0 = no error, otherwise <0. + virtual long GetViewFocusDistance(double &distance) const = 0; + + /// + /// Gets the camera's/view's field of view. + /// + /// The field of view in radians. + /// 0 = no error, otherwise <0. + virtual long GetViewFOV(double &fov) const = 0; + + /// + /// Gets the camera/view frustum. + /// + /// The camera/view . + /// 0 = no error, otherwise <0. + virtual long GetViewFrustum(navlib::frustum_t &frustum) const = 0; + + /// + /// Get's the view's projection type + /// + /// true for a perspective view, false for an orthographic view. + /// 0 = no error, otherwise <0. + virtual long GetIsViewPerspective(navlib::bool_t &perspective) const = 0; + + /// + /// Gets a value indicating whether the view can be rotated. + /// + /// true if the view can be rotated, false otherwise. + /// 0 = no error, otherwise <0. + virtual long GetIsViewRotatable(navlib::bool_t &isRotatable) const = 0; + + /// + /// Sets the camera affine matrix. + /// + /// The camera/view . + /// 0 = no error, otherwise <0. + virtual long SetCameraMatrix(const navlib::matrix_t& matrix) = 0; + + /// + /// Sets the camera's target position. + /// + /// The position of the camera target in world coordinates. + /// 0 = no error, otherwise <0. + /// Free cameras do not have a target. + virtual long SetCameraTarget(const navlib::point_t &target) = 0; + + /// + /// Sets the position of the pointer on the near clipping plane. + /// + /// The in world coordinates of the + /// pointer. + /// 0 = no error, otherwise <0. + virtual long SetPointerPosition(const navlib::point_t& position) = 0; + + /// + /// Sets the extents of the view. + /// + /// A representing the extents of the + /// view. + /// 0 = no error, otherwise <0. + virtual long SetViewExtents(const navlib::box_t& extents) = 0; + + /// + /// Sets the camera's/view's field of view. + /// + /// The field of view in radians. + /// 0 = no error, otherwise <0. + virtual long SetViewFOV(double fov) = 0; + + /// + /// Sets the camera/view frustum. + /// + /// The camera/view . + /// 0 = no error, otherwise <0. + virtual long SetViewFrustum(const navlib::frustum_t& frustum) = 0; +}; +} // namespace Navigation3D +} // namespace SpaceMouse +} // namespace TDx +#endif // IView_HPP_INCLUDED diff --git a/thirdparty/3DConnexion/inc/navlib/navlib.h b/thirdparty/3DConnexion/inc/navlib/navlib.h new file mode 100644 index 00000000..af833510 --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib.h @@ -0,0 +1,672 @@ +#ifndef NAVLIB_H_INCLUDED_ +#define NAVLIB_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib.h 19940 2023-01-25 07:17:44Z mbonk $ +// +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file describes the interface for navigating in a 2D or 3D view. +// +// ************************************************************************************************* +// + +#include +/// +/// Contains the navigation library API types and functions +/// +/// +/// The functions and types describe an interface for navigating in a 2D or 3D view. +/// +/// In this scheme, a 3dconnexion library is responsible for calculating the position of the camera +/// viewing the scene or object as well as displaying the settings and for supporting user +/// customization. +/// +/// +/// The application is responsible for passing the description of an interface of the 2D/3D view to +/// the 3dconnexion library, and for reacting to the changes to the properties identified by the +/// 3dconnexion library. +/// +/// +NAVLIB_BEGIN_ + +// ************************************************************************************************ +// Properties + +/// +/// Property set by the client to indicate that the connection is currently active. +/// +/// +/// The type is and is +/// . +/// Clients that have multiple navigation instances open need to inform the navlib which of +/// them is the target for 3D Mouse input. They do this by setting the active_k property of a +/// navigation instance to true. +/// +static const property_t active_k = "active"; + +/// +/// Property that a client sets to indicate it has keyboard focus. +/// +/// +/// The type is and is +/// . +/// Clients that run in container applications via the NLServer proxy set this property to +/// indicate keyboard focus. This will set 3DMouse focus to the navlib connection. +/// +static const property_t focus_k = "focus"; + +/// +/// Client property that the navlib sets when a motion model is active. +/// +/// +/// The type is and is +/// . +/// The motion_k property is set to true by the navlib to notify +/// the client that it is executing a motion model and will update the camera matrix regularly. This +/// is useful for clients that need to run an animation loop. When the navlib has finished +/// navigating the camera position it will set the property to false. By setting motion_k to false, +/// a client may temporarily interrupt a navigation communication and force the Navlib to +/// reinitialize the navigation. +/// +static const property_t motion_k = "motion"; + +/// +/// Specifies the transform from the client's coordinate system to the navlib coordinate system. +/// +/// +/// The type is and is +/// . +/// The Navigation Library coordinate system is Y up, X to the right and Z out of the screen. +/// This property is queried directly after new navigation instance is created. This allows the +/// client to specify the other properties using the coordinate system used in the client. For the +/// keep Y up ('Lock Horizon') algorithm to work correctly a non-identity matrix needs to be +/// specified whenever the ground plane is not the X-Z plane. +/// +static const property_t coordinate_system_k = "coordinateSystem"; + +/* Frame properties*/ +/// +/// Specifies the begin and end of a navigation transaction. +/// +/// +/// The type is and is +/// . +/// The Navigation Library can set more than one client property for a single navigation +/// frame. For example when navigating in an orthographic projection possibly both the view affine +/// and extents will be modified depending on the 3DMouse input. The Navigation Library sets the +/// transaction_k property to a value >0 at the beginning of a navigation frame and to 0 at the end. +/// Clients that need to actively refresh the view can trigger the refresh when the value is set to +/// 0. +/// +static const property_t transaction_k = "transaction"; + +/// +/// Specifies the time stamp of an animation frame in milliseconds. +/// +/// +/// The type is and is +/// . +/// When the frame_timing_source_k property is set to 1, the client initiates a frame +/// transaction by informing the Navigation Library of the frame time. When the value is 0, the +/// Navigation Library attempts to synchronize the frames to the monitor vertical blanking +/// rate. +/// +static const property_t frame_time_k = "frame.time"; + +/// +/// Specifies the source of the frame timing. +/// +/// +/// The type is and is +/// . +/// By setting the frame_timing_source_k property to 1, the client application informs the +/// Navigation Library that the client has an animation loop and will be the source of the frame +/// timing. +/// +static const property_t frame_timing_source_k = "frame.timingSource"; + +/// +/// Specifies whether a device is present +/// +/// +/// The type is and is +/// . +/// Currently this always returns true. +/// +static const property_t device_present_k = "device.present"; + +/// +/// Defines a set of commands. +/// +/// +/// The type is * and is +/// . +/// Command sets can be considered to be button banks. The set can be either the complete list +/// of commands that are available in the application or a single set of commands for a specific +/// application context. The navlib will not query the application for this property. It is the +/// responsibility of the application to update this property when commands are to be made available +/// to the user. +/// +static const property_t commands_tree_k = "commands.tree"; + +/// +/// The active command. +/// +/// +/// The type is and is +/// . +/// When the user presses a 3DMouse button that has been assign an application command +/// exposed by the commands_tree_k property, the navlib will write this property. The string value +/// will be the corresponding id passed in the commands_tree_k property. Generally the navlib will +/// set this property to an empty string when the corresponding button has been released. +/// +static const property_t commands_activeCommand_k = "commands.activeCommand"; + +/// +/// Specifies the active set of commands. +/// +/// +/// The type is and is +/// . +/// In applications that have exposed multiple command sets this property needs to be set to +/// define the command set that is active. The navlib will not query the application for this +/// property. It is the responsibility of the application to update this property when the set of +/// commands need to be changed. Normally this will be due to change in application state and may +/// correspond to a menu/toolbar change. If only a single set of commands has been defined, this +/// property defaults to that set. +/// +static const property_t commands_activeSet_k = "commands.activeSet"; + +/// +/// Specifies an array of images for the 3Dconnexion UI. +/// +/// +/// The type is and is +/// . +/// An image with the same as a command +/// will be associated with that command in the 3Dconnexion +/// UI. +/// +static const property_t images_k = "images"; + +/* view properties */ +/// +/// Specifies the transformation matrix of the view camera. +/// +/// +/// The type is and is +/// . +/// This matrix specifies the camera to world transformation of the view. That is, +/// transforming the position (0, 0, 0) by this matrix yields the position of the camera in world +/// coordinates. The navlib will, generally, query this matrix at the beginning of a navigation +/// action and then set the property once per frame. +/// +static const property_t view_affine_k = "view.affine"; + +/// +/// Specifies the plane equation of the construction plane. +/// +/// +/// The type is and is +/// . +/// The plane equation is used by the Navigation Library to distinguish views used for +/// construction in orthographic projections: typically the top, right left etc. views. The +/// Navigation Library assumes that when the camera's look-at axis is parallel to the plane normal, +/// the view should not be rotated. +/// +static const property_t view_constructionPlane_k = "view.constructionPlane"; + +/// +/// Specifies the orthographic extents of the view in camera coordinates. +/// +/// +/// The type is and is +/// . +/// The orthographic extents of the view are returned as a bounding box in world units +/// relative to the camera/view frame. The view frame is a right-handed coordinate system centered +/// on the view with x to the right and y up. The Navigation Library will only access this property +/// if the view is orthographic. +/// +static const property_t view_extents_k = "view.extents"; + +/// +/// Specifies the vertical field-of-view of a perspective camera/view in radians. +/// +/// +/// The type is and is +/// . +/// +static const property_t view_fov_k = "view.fov"; + +/// +/// Specifies the frustum of a perspective camera/view in camera coordinates. +/// +/// +/// The type is and is +/// . +/// The navlib uses this property to calculate the field-of-view of the perspective camera. +/// The frustum is also used in algorithms that need to determine if the model is currently visible. +/// The navlib will not write to this property. Instead, if necessary, the navlib will write to the +/// property and leave the client to change the frustum as it +/// wishes. +/// +static const property_t view_frustum_k = "view.frustum"; + +/// +/// Specifies whether the projection type of the view/camera is perspective. +/// +/// +/// The type is and is +/// . +/// This property defaults to true. If the client does not supply a function for the navlib to +/// query the view's projection (which it will generally do at the onset of motion), then it must +/// set the property in the navlib if the projection is orthographic or when it changes. +/// +static const property_t view_perspective_k = "view.perspective"; + +/// +/// Specifies the position of the target of the view/camera. +/// +/// +/// The type is and is +/// . +/// The view interest. +/// +static const property_t view_target_k = "view.target"; + +/// +/// Specifies whether the view can be rotated. +/// +/// +/// The type is and is +/// . +/// This property is generally used to differentiate between orthographic 3D views and views +/// that can only be panned and zoomed such as plan views. +/// +static const property_t view_rotatable_k = "view.rotatable"; + +/// +/// Specifies the distance between the view camera and the object the user is focused on. +/// +/// +/// The type is and is +/// . +/// This property is used to define the distance to the users object of interest and determines +/// the translation speed sensitivity of the camera or SpaceMouse. +/// +static const property_t view_focusDistance_k = "view.focusDistance"; + +/// +/// Specifies the orientation of the view designated as the front view. +/// +/// +/// The type is and is +/// . +/// The Navigation Library will only query the value of this property when the connection is +/// created. It is used to orientate the model to one of the 'Front', 'Back', 'Right', 'Left' etc. +/// views in response to the respective pre-defined view commands. If the orientation of the front +/// view is redefined after the connection is opened by the user, the client application is required +/// to update the property to the new value. +/// +static const property_t views_front_k = "views.front"; + +/// +/// Specifies the position of the rotation pivot. +/// +/// +/// The type is and is +/// . +/// The Navigation Library will generally set property when +/// navigation ends. The position will depend on which pivot model is being used. The application +/// can set the pivot to a fix position by setting this property. A side effect of the application +/// setting the property is that the property is set to true. +/// +static const property_t pivot_position_k = "pivot.position"; + +/// +/// Specifies whether the position of the rotation pivot is set by the user. +/// +/// +/// The type is and is +/// . +/// With the property set to true, the Navigation Library will disable the internal pivot +/// position algorithms. +/// +static const property_t pivot_user_k = "pivot.user"; + +/// +/// Specifies whether the rotation pivot widget is visible. +/// +/// +/// The type is and is +/// . +/// Set by the Navigation Library when it wants to set the visibility of the pivot used for +/// the 3D navigation. This will be dependent on the user setting for the pivot visibility in the +/// 3Dconnexion Settings configuration and whether the Navigation Library is actively navigating +/// the scene. +/// +static const property_t pivot_visible_k = "pivot.visible"; + +/// +/// Specifies the origin of the ray used for hit-testing. +/// +/// +/// The type is and is +/// . +/// Set by the Navigation Library. The location is relative to the world coordinate +/// system. +/// +static const property_t hit_lookfrom_k = "hit.lookfrom"; + +/// +/// Specifies the direction of the ray used for hit-testing. +/// +/// +/// The type is and is +/// . +/// Set by the Navigation Library. The direction is relative to the world coordinate +/// system frame. +/// +static const property_t hit_direction_k = "hit.direction"; + +/// +/// Specifies the diameter of the ray used for hit-testing. +/// +/// +/// The type is and is +/// . +/// Set by the Navigation Library. This is the diameter of the aperture on the frustum near +/// plane. In a perspective project the ray is a cone. +/// +static const property_t hit_aperture_k = "hit.aperture"; + +/// +/// Specifies the point of the model that is hit by the ray originating from +/// . +/// +/// +/// The type is and is +/// . +/// This property is queried by the navlib. The navlib will generally calculate if it is +/// possible to hit a part of the model from the and +/// properties before setting up the hit-test properties and +/// querying the property. The position is relative to the world coordinate system frame. +/// +static const property_t hit_lookat_k = "hit.lookat"; + +/// +/// Specifies whether the hit-testing is limited solely to the current selection set. +/// +/// +/// The type is and is +/// . +/// +static const property_t hit_selectionOnly_k = "hit.selectionOnly"; + +/// +/// Specifies the transformation matrix of the selection set. +/// +/// +/// The type is and is +/// . +/// This matrix specifies the object to world transformation of the selection set. That is, +/// transforming the position (0, 0, 0) by this matrix yields the position of the set in world +/// coordinates. The navlib will, generally, query this matrix at the beginning of a navigation +/// action that involves moving the selection and then set the property once per frame. +/// +static const property_t selection_affine_k = "selection.affine"; + +/// +/// Specifies whether the selection set is empty. +/// +/// +/// The type is and is +/// . +/// When true, nothing is selected. +/// +static const property_t selection_empty_k = "selection.empty"; + +/// +/// Specifies the bounding box of the selection set. +/// +/// +/// The type is and is +/// . +/// The extents of the selection are returned as a bounding box in world coordinates. The +/// Navigation Library will only access this property if the +/// property is false. +/// +static const property_t selection_extents_k = "selection.extents"; + +/// +/// Specifies the bounding box of the model. +/// +/// +/// The type is and is +/// . +/// +static const property_t model_extents_k = "model.extents"; + +/// +/// Specifies the plane equation of the floor. /// +/// +/// The type is and is +/// . +/// The plane equation is used by the Navigation Library to determine the floor for the +/// walk navigation mode, where the height of the eye is fixed to 1.5m above the floor plane. +/// The floor need not be parallel to the world ground plane. +/// Introduced in 3DxWare 10 version 10.8.12. +static const property_t model_floorPlane_k = "model.floorPlane"; + +/// +/// Specifies the length of the model/world units in meters. /// +/// +/// The type is and is +/// . +/// The conversion factor is used by the Navigation Library to calculate the height above the +/// floor in walk mode and the speed in the first person motion model. +/// Introduced in 3DxWare 10 version 10.8.12. +static const property_t model_unitsToMeters_k = "model.unitsToMeters"; + +/// +/// Specifies the position of the mouse cursor. on the projection plane in world coordinates. +/// +/// +/// The type is and is +/// . +/// The position of the mouse cursor is in world coordinates on the projection plane. For a +/// perspective projection the Navigation Library uses the near clipping as the projection plane. +/// In OpenGL the position would typically be retrieved using gluUnProject with winZ set to +/// 0.0. +/// +static const property_t pointer_position_k = "pointer.position"; + +/// +/// V3DK press event. +/// +static const property_t events_keyPress_k = "events.keyPress"; + +/// +/// V3DK release event. +/// +static const property_t events_keyRelease_k = "events.keyRelease"; + +/// +/// Used to query and apply settings in the 3Dconnexion Settings UI. +/// +/// +/// The type is and is +/// . +/// The property settings_k does not actually exist in the Navigation Library. To read or +/// write a property to the application profile, the settings_k needs to be appended with "." and +/// the name of the profile property."settings.MoveObjects" is used to read or write the +/// value of the "MoveObjects" property in the profile settings. +/// +static const property_t settings_k = "settings"; + +/// +/// Specifies the change revision of the profile settings. +/// +/// +/// The type is and is +/// . +/// This property is incremented when the settings changed. The value is only valid for the +/// current connection to the Navigation Library and is not persistent over multiple sessions. If +/// the client needs to know the value of a 3Dconnexion profile setting it should re-read the value +/// when settings_changed_k is changed. +/// +static const property_t settings_changed_k = "settings.changed"; + +// Workaround for error C2099: initializer is not a constant when compiling .c +#if __cplusplus +/// +/// Defines the type of a property and the access required of the client application. +/// +static const propertyDescription_t propertyDescription[] = { + /* property, type, required client access */ + {active_k, bool_type, eno_access}, + {focus_k, bool_type, eno_access}, + {motion_k, bool_type, ewrite_access}, + {coordinate_system_k, matrix_type, eread_access}, + {device_present_k, bool_type, eno_access}, + {events_keyPress_k, long_type, ewrite_access}, + {events_keyRelease_k, long_type, ewrite_access}, + + /* frame properties*/ + {transaction_k, long_type, ewrite_access}, + {frame_time_k, double_type, eread_access}, + {frame_timing_source_k, long_type, eread_access}, + + /* view properties */ + {view_affine_k, matrix_type, eread_write_access}, + {view_constructionPlane_k, plane_type, eread_access}, + {view_extents_k, box_type, eread_write_access}, + {view_fov_k, float_type, eread_write_access}, + {view_frustum_k, frustum_type, eread_access}, + {view_perspective_k, bool_type, eread_access}, + {view_rotatable_k, bool_type, eread_access}, + {view_target_k, point_type, eread_access}, + {view_focusDistance_k, float_type, eread_access}, + + /* views properties*/ + {views_front_k, matrix_type, eread_access}, + + /* pivot properties */ + {pivot_position_k, point_type, eread_write_access}, + {pivot_user_k, bool_type, eno_access}, + {pivot_visible_k, bool_type, ewrite_access}, + + /* hit-test properties */ + {hit_lookfrom_k, point_type, ewrite_access}, + {hit_direction_k, vector_type, ewrite_access}, + {hit_aperture_k, float_type, ewrite_access}, + {hit_lookat_k, point_type, eread_access}, + {hit_selectionOnly_k, bool_type, ewrite_access}, + + /* selection properties */ + {selection_affine_k, matrix_type, eread_write_access}, + {selection_empty_k, bool_type, eread_access}, + {selection_extents_k, box_type, eread_access}, + + /* model properties */ + {model_extents_k, box_type, eread_access}, + {model_floorPlane_k, plane_type, eread_access}, + {model_unitsToMeters_k, float_type, eread_access}, + + /* pointer (cursor) properties */ + {pointer_position_k, point_type, eread_access}, + + /* commands properties */ + {commands_tree_k, actionnodeexptr_type, eno_access}, + {commands_activeSet_k, string_type, eno_access}, + {commands_activeCommand_k, string_type, ewrite_access}, + + /* images properties*/ + {images_k, imagearray_type, eno_access}, + + /* settings property*/ + {settings_k, string_type, eno_access}, + {settings_changed_k, long_type, ewrite_access}}; +#endif + +/********************************************************************************************** +Functions exported from the library + **********************************************************************************************/ + +/// +/// Creates a new navigation instance. +/// +/// The client specifies the name of the instance and the properties that are available +/// for querying and updating by the navigation framework. +/// A pointer to a for the new navigation +/// instance. +/// The name of the application. +/// An array of structures containing the +/// property name, accessor and mutator functions that the client exposes to the navigation +/// instance. +/// The number of entries passed in the +/// property_accessors parameter. +/// Pointer to a . This parameter is optional +/// and may be null. +/// 0 on success or a navlib error, see and +/// . +NAVLIB_DLLAPI_ long __cdecl NlCreate(nlHandle_t *pnh, const char *appname, + const accessor_t property_accessors[], size_t accessor_count, + const nlCreateOptions_t *options); + +/// +/// Closes an open navigation instance handle and destroys the navigation instance. +/// +/// A valid of an open navigation instance. +/// 0 if the function succeeds, otherwise a navlib error, see +/// and . +NAVLIB_DLLAPI_ long __cdecl NlClose(nlHandle_t nh); + +/// +/// Read the value of a property cached in the navlib. +/// +/// The of the open navigation instance. +/// The name of the property whose value is being queried. +/// A pointer to a that contains the property value when +/// the function returns. +/// 0 if the function succeeds, otherwise a navlib error, see +/// and . +NAVLIB_DLLAPI_ long __cdecl NlReadValue(nlHandle_t nh, property_t name, value_t *value); + +/// +/// Write the value for a property to the navlib. +/// +/// The of the open navigation instance. +/// The name of the property whose value is to be written. +/// A pointer to a that contains the new property +/// value. +/// 0 if the function succeeds, otherwise a navlib error, see +/// and . +NAVLIB_DLLAPI_ long __cdecl NlWriteValue(nlHandle_t nh, property_t name, const value_t *value); + +/// +/// Query the type of a navlib property. +/// +/// The name of the property whose type is to be queried. +/// One of the values. +NAVLIB_DLLAPI_ propertyType_t __cdecl NlGetType(property_t name); + +NAVLIB_END_ + +#endif // NAVLIB_H_INCLUDED_ diff --git a/thirdparty/3DConnexion/inc/navlib/navlib_defines.h b/thirdparty/3DConnexion/inc/navlib/navlib_defines.h new file mode 100644 index 00000000..37a0c6d6 --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib_defines.h @@ -0,0 +1,72 @@ +#ifndef NAVLIB_DEFINES_H_INCLUDED_ +#define NAVLIB_DEFINES_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib_defines.h 19940 2023-01-25 07:17:44Z mbonk $ +// +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file defines the macros used in the 3dconnexion interface and header files. +// +// ************************************************************************************************* +// + +// Invalid handle +#define INVALID_NAVLIB_HANDLE 0 + +// Navlib facility used to generate error codes +// Note this is identical to FACILITY_ITF on windows +#define FACILITY_NAVLIB 4 + +// resources +#define NAVLIB_IDB_ManualPivot 0x6004 +#define NAVLIB_IDB_AutoPivot 0x6005 + +#if defined(__cplusplus) +#define NAVLIB_BEGIN_ namespace navlib { +#define NAVLIB_END_ } +#define NAVLIB_ ::navlib:: +#define USING_NAVLIB_ using namespace navlib; +#else +#define NAVLIB_BEGIN_ +#define NAVLIB_END_ +#define NAVLIB_ +#define USING_NAVLIB_ +#endif + +#if defined(_MSC_VER) && defined(NAVLIB_EXPORTS) +#define NAVLIB_DLLAPI_ extern "C" __declspec(dllexport) +#elif defined(__cplusplus) +#define NAVLIB_DLLAPI_ extern "C" +#else +#define NAVLIB_DLLAPI_ +#endif + +#ifndef NOEXCEPT +#if defined(_MSC_VER) && (_MSC_VER <= 1800) +#ifdef _NOEXCEPT +#define NOEXCEPT _NOEXCEPT +#else +#define NOEXCEPT +#endif +#else +#define NOEXCEPT noexcept +#endif +#endif + +#endif // NAVLIB_DEFINES_H_INCLUDED_ diff --git a/thirdparty/3DConnexion/inc/navlib/navlib_error.h b/thirdparty/3DConnexion/inc/navlib/navlib_error.h new file mode 100644 index 00000000..68e1d11f --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib_error.h @@ -0,0 +1,88 @@ +#ifndef NAVLIB_ERROR_H_INCLUDED_ +#define NAVLIB_ERROR_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib_error.h 19940 2023-01-25 07:17:44Z mbonk $ +// +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file defines the classes used for error reporting. +// +// ************************************************************************************************* +// + +#include + +#include + + +namespace std { +template <> struct is_error_code_enum : true_type {}; +} // namespace std + +namespace { // Anonymous namespace +/// +/// Navigation library error category. +/// +struct navlib_error_category : public std::error_category { + typedef std::error_category base_type; + +public: + navlib_error_category() NOEXCEPT { + } + + const char *name() const NOEXCEPT override { + return "navlib"; + } + + std::string message(int errorValue) const override { + namespace navlib_errc = navlib::navlib_errc; + switch (static_cast(errorValue)) { + case navlib_errc::property_not_found: + return "Cannot locate the requested navlib property."; + + case navlib_errc::invalid_function: + return "The requested function is not valid."; + + case navlib_errc::insufficient_buffer: + return "Insufficient buffer space."; + + default: + return std::generic_category().message(errorValue); + } + } +}; + +/// +/// Navigation library error category. +/// +static const navlib_error_category navlib_category; +} // namespace + +NAVLIB_BEGIN_ +/// +/// Makes a . +/// +/// The Navigation library error. +/// A with the Navigation library category. +inline std::error_code make_error_code(navlib_errc::navlib_errc_t errc) { + std::error_code ec(static_cast(errc), navlib_category); + return ec; +} +NAVLIB_END_ // namespace navlib +#endif /* NAVLIB_ERROR_H_INCLUDED_ */ diff --git a/thirdparty/3DConnexion/inc/navlib/navlib_operators.h b/thirdparty/3DConnexion/inc/navlib/navlib_operators.h new file mode 100644 index 00000000..a7ecd698 --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib_operators.h @@ -0,0 +1,105 @@ +#ifndef NAVLIB_OPERATORS_H_INCLUDED_ +#define NAVLIB_OPERATORS_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib_operators.h 19944 2023-01-25 14:56:02Z mbonk $ +// +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file defines the operator overloads for variable types used in the 3dconnexion +// interface. +// +// ************************************************************************************************* +// +#include + +// stdlib +#include +#include + +NAVLIB_BEGIN_ + +/// +/// Compare floating point numbers. +/// +/// First value to compare. +/// Second value to compare. +/// Maximum relative error. +/// +/// +/// From https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition. +/// Copyright Bruce Dawson. +/// +template bool equals(T a, T b, T epsilon = static_cast(FLT_EPSILON)) { + T diff = fabs(a - b); + if (diff < epsilon) { + return true; + } + a = fabs(a); + b = fabs(b); + T largest = (a > b) ? a : b; + if (diff <= largest * epsilon) { + return true; + } + return false; +} + +inline bool operator==(const vector_t &lhs, const vector_t &rhs) { + return (equals(lhs.x, rhs.x) && equals(lhs.y, rhs.y) && equals(lhs.z, rhs.z)); +} + +inline bool operator!=(const vector_t &lhs, const vector_t &rhs) { + return !(lhs == rhs); +} + +inline bool operator==(const point_t &lhs, const point_t &rhs) { + return (equals(lhs.x, rhs.x) && equals(lhs.y, rhs.y) && equals(lhs.z, rhs.z)); +} + +inline bool operator!=(const point_t &lhs, const point_t &rhs) { + return !(lhs == rhs); +} + +inline bool operator==(const box_t &lhs, const box_t &rhs) { + return lhs.min == rhs.min && lhs.max == rhs.max; +} + +inline bool operator!=(const box_t &lhs, const box_t &rhs) { + return !(lhs == rhs); +} + +inline bool operator==(const matrix_t &lhs, const matrix_t &rhs) { + for (size_t i = 0; i < sizeof(rhs) / sizeof(rhs[0]); ++i) { + if (!equals(lhs[i], rhs[i])) { + return false; + } + } + return true; +} + +inline bool operator!=(const matrix_t &lhs, const matrix_t &rhs) { + return !(lhs == rhs); +} + +inline nlOptions_t operator|(nlOptions_t lhs, nlOptions_t rhs) { + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +NAVLIB_END_ + +#endif /* NAVLIB_OPERATORS_H_INCLUDED_ */ \ No newline at end of file diff --git a/thirdparty/3DConnexion/inc/navlib/navlib_ostream.h b/thirdparty/3DConnexion/inc/navlib/navlib_ostream.h new file mode 100644 index 00000000..266e74d4 --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib_ostream.h @@ -0,0 +1,237 @@ +#ifndef NAVLIB_OSTREAM_INCLUDED_ +#define NAVLIB_OSTREAM_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib_ostream.h 19940 2023-01-25 07:17:44Z mbonk $ +// +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file defines stream operators for the navlib types. +// +// ************************************************************************************************* +// + +#include +// C++ convenience functions + +#include +#include +#include +#include + +NAVLIB_BEGIN_ +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const vector_t &vector) { + stream << std::setprecision(std::numeric_limits::digits10 + 1); + stream << "[" << vector.x << ", " << vector.y << ", " << vector.z << "]"; + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const point_t &position) { + stream << std::setprecision(std::numeric_limits::digits10 + 1); + stream << "[" << position.x << ", " << position.y << ", " << position.z << "]"; + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const plane_t &plane) { + stream << std::setprecision(std::numeric_limits::digits10 + 1); + stream << "[" << plane.n.x << ", " << plane.n.y << ", " << plane.n.z << ", " << plane.d << "]"; + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const box_t &box) { + stream << std::setprecision(std::numeric_limits::digits10 + 1); + stream << box.min << ", " << box.max; + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const frustum_t &frustum) { + stream << std::setprecision(std::numeric_limits::digits10 + 1); + stream << "[" << frustum.left << ", " << frustum.right << ", " << frustum.bottom << ", " + << frustum.top << ", " << frustum.nearVal << ", " << frustum.farVal << "]"; + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const matrix_t &matrix) { + stream << std::endl; + stream << std::setprecision(std::numeric_limits::digits10 + 1); + stream << "\t[" << matrix.m00 << ", " << matrix.m01 << ", " << matrix.m02 << ", " << matrix.m03 + << "]" << std::endl; + stream << "\t[" << matrix.m10 << ", " << matrix.m11 << ", " << matrix.m12 << ", " << matrix.m13 + << "]" << std::endl; + stream << "\t[" << matrix.m20 << ", " << matrix.m21 << ", " << matrix.m22 << ", " << matrix.m23 + << "]" << std::endl; + stream << "\t[" << matrix.m30 << ", " << matrix.m31 << ", " << matrix.m32 << ", " << matrix.m33 + << "]"; + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const struct siResource_s &resource) { + stream << "{file_name: " << (resource.file_name ? resource.file_name : "nullptr") + << ", id: " << (resource.id ? resource.id : "nullptr") + << ", type: " << (resource.type ? resource.type : "nullptr") + << ", index: " << resource.index << "}"; + + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const struct siImageFile_s &file) { + stream << "{file_name: " << (file.file_name ? file.file_name : "nullptr") + << ", index: " << file.index << "}"; + + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const struct siImageData_s &image) { + stream << "{data: 0x" << std::hex << reinterpret_cast(image.data) << std::dec + << ", size: " << image.size << ", index: " << image.index << "}"; + + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const imagearray_t &images) { + stream << "count: " << images.count; + + std::string indent("\n"); + indent.resize(5, ' '); + + for (size_t i = 0; i < images.count; ++i) { + SiImage_t const &image = images.p[i]; + stream << indent << "{size: " << image.size << ", id: " << (image.id ? image.id : "nullptr"); + if (image.type == e_image_file) + stream << ", type: e_image_file, " << image.file; + else if (image.type == e_resource_file) + stream << ", type: e_resource_file, " << image.resource; + if (image.type == e_image) + stream << ", type: e_image, " << image.image; + else + stream << ", type: e_none"; + stream << "}"; + } + return stream; +} + +template +void StreamActionNodeHeader(std::basic_ostream &stream, + const SiActionNodeEx_t &node, size_t level) { + std::string indent("\n"); + indent.resize(4 * level + 1, ' '); + + stream << indent << "{size: " << node.size << ", type: " << node.type + << ", id: " << (node.id ? node.id : "nullptr") + << ", label: " << (node.label ? node.label : "nullptr") + << ", description: " << (node.description ? node.description : "nullptr") << "}"; + if (node.children != nullptr) + StreamActionNodeHeader(stream, *node.children, level + 1); + if (node.next != nullptr) + StreamActionNodeHeader(stream, *node.next, level); +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const SiActionNodeEx_t &node) { + StreamActionNodeHeader(stream, node, 1); + return stream; +} + +template +std::basic_ostream &operator<<(std::basic_ostream &stream, + const value_t &value) { + try { + switch (value.type) { + case voidptr_type: + stream << value.p; + break; + case bool_type: + stream << (value.b ? "true" : "false"); + break; + case long_type: + stream << value.l; + break; + case float_type: + stream << std::setprecision(std::numeric_limits::digits10 + 1) << value.f; + break; + case double_type: + stream << std::setprecision(std::numeric_limits::digits10 + 2) << value.d; + break; + case point_type: + stream << value.point; + break; + case vector_type: + stream << value.vector; + break; + case matrix_type: + stream << value.matrix; + break; + case string_type: + if (value.string.p) + stream << value.string.p; + else + stream << "empty"; + break; + case actionnodeexptr_type: + stream << *value.pnode; + break; + case imagearray_type: + stream << value.imagearray; + break; + case plane_type: + stream << value.plane; + break; + case box_type: + stream << value.box; + break; + case frustum_type: + stream << value.frustum; + break; + case cstr_type: + if (value.cstr_.p) + stream << value.cstr_.p; + else + stream << "empty"; + break; + default: + stream << "null"; + break; + } + } catch (std::runtime_error &e) { + stream << "std::runtime_error " << e.what(); + } + return stream; +} +NAVLIB_END_ +#endif // NAVLIB_OSTREAM_INCLUDED_ diff --git a/thirdparty/3DConnexion/inc/navlib/navlib_templates.h b/thirdparty/3DConnexion/inc/navlib/navlib_templates.h new file mode 100644 index 00000000..e7969530 --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib_templates.h @@ -0,0 +1,527 @@ +#ifndef NAVLIB_TEMPLATES_H_INCLUDED_ +#define NAVLIB_TEMPLATES_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib_templates.h 19940 2023-01-25 07:17:44Z mbonk $ +// +// 06/17/20 MSB Changed condition evaluation away from boolean macros to avoid C4668 +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file defines the templates used in the 3dconnexion interface. +// +// ************************************************************************************************* +// +#if (defined _MSC_VER && _MSC_VER < 1900) +#define CONSTEXPR const +#else +#define CONSTEXPR constexpr +#define has_constexpr +#endif + +namespace navlib { +template struct property_type_v { + static CONSTEXPR propertyType_t type = unknown_type; +#ifdef has_constexpr + static constexpr char const *name = "unknown_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +template const char *property_type_v::name = "unknown_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = voidptr_type; +#ifdef has_constexpr + static constexpr char const *name = "voidptr_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "voidptr_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = bool_type; +#ifdef has_constexpr + static constexpr char const *name = "bool_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "bool_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = long_type; +#ifdef has_constexpr + static constexpr char const *name = "long_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "long_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = float_type; +#ifdef has_constexpr + static constexpr char const *name = "float_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "float_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = double_type; +#ifdef has_constexpr + static constexpr char const *name = "double_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "double_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = point_type; +#ifdef has_constexpr + static constexpr char const *name = "point_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "point_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = vector_type; +#ifdef has_constexpr + static constexpr char const *name = "vector_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "vector_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = plane_type; +#ifdef has_constexpr + static constexpr char const *name = "plane_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "plane_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = box_type; +#ifdef has_constexpr + static constexpr char const *name = "box_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "box_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = frustum_type; +#ifdef has_constexpr + static constexpr char const *name = "frustum_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "frustum_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = matrix_type; +#ifdef has_constexpr + static constexpr char const *name = "matrix_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "matrix_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = actionnodeexptr_type; +#ifdef has_constexpr + static constexpr char const *name = "actionnodeexptr_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const + char *property_type_v::name = "actionnodeexptr_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = string_type; +#ifdef has_constexpr + static constexpr char const *name = "string_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "string_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = cstr_type; +#ifdef has_constexpr + static constexpr char const *name = "cstr_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "cstr_type"; +#endif + +template <> struct property_type_v { + static CONSTEXPR propertyType_t type = imagearray_type; +#ifdef has_constexpr + static constexpr char const *name = "imagearray_type"; +#else + static const char *name; +#endif +}; +#ifndef has_constexpr +__declspec(selectany) const char *property_type_v::name = "imagearray_type"; +#endif + +template struct remove_cvref { + typedef typename std::remove_cv::type>::type type; +}; + +// navlib property type from variable type +template struct property_type : property_type_v::type> { + typedef property_type_v::type> base_type; + typedef propertyType_t value_type; + CONSTEXPR value_type operator()() const { + return base_type::value; + } +#ifdef has_constexpr + constexpr operator value_type() const { + return base_type::value; + } + constexpr operator char *() const { + return base_type::name; + } +#else + operator const value_type() const { + return base_type::value; + } + operator const char *() const { + return base_type::name; + } +#endif +}; + +template struct value_member {}; // primary template + +// specialization for void* +template struct value_member { + T operator()(V &v) { + return v.p; + } +}; + +// specialization for void** +template struct value_member { + T operator()(V &v) { + return &v.p; + } +}; + +// specialization for bool +template struct value_member { + T operator()(V &v) { + return v.b != 0; + } +}; + +// specialization for bool_t +template struct value_member { + T operator()(V &v) { + return v.b; + } +}; + +// specialization for bool_t* +template struct value_member { + T operator()(V &v) { + return &v.b; + } +}; + +// specialization for int +template struct value_member { + T operator()(V &v) { + return v.l; + } +}; + +// specialization for long +template struct value_member { + T operator()(V &v) { + return v.l; + } +}; + +// specialization for long* +template struct value_member { + T operator()(V &v) { + return &v.l; + } +}; + +// specialization for float +template struct value_member { + T operator()(V &v) { + return v.f; + } +}; + +// specialization for float* +template struct value_member { + T operator()(V &v) { + return &v.f; + } +}; + +// specialization for double +template struct value_member { + T operator()(V &v) { + return v.d; + } +}; + +// specialization for double* +template struct value_member { + T operator()(V &v) { + return &v.d; + } +}; + +// specialization for point_t +template struct value_member { + T operator()(V &v) { + return v.point; + } +}; + +// specialization for point_t* +template struct value_member { + T operator()(V &v) { + return &v.point; + } +}; + +// specialization for vector_t +template struct value_member { + T operator()(V &v) { + return v.vector; + } +}; + +// specialization for vector_t* +template struct value_member { + T operator()(V &v) { + return &v.vector; + } +}; + +// specialization for plane_t +template struct value_member { + T operator()(V &v) { + return v.plane; + } +}; + +// specialization for plane_t* +template struct value_member { + T operator()(V &v) { + return &v.plane; + } +}; + +// specialization for box_t +template struct value_member { + T operator()(V &v) { + return v.box; + } +}; + +// specialization for box_t* +template struct value_member { + T operator()(V &v) { + return &v.box; + } +}; + +// specialization for frustum_t +template struct value_member { + T operator()(V &v) { + return v.frustum; + } +}; + +// specialization for frustum_t* +template struct value_member { + T operator()(V &v) { + return &v.frustum; + } +}; + +// specialization for matrix_t +template struct value_member { + T operator()(V &v) { + return v.matrix; + } +}; + +// specialization for matrix_t* +template struct value_member { + T operator()(V &v) { + return &v.matrix; + } +}; + +// specialization for SiActionNodeEx_t* +template struct value_member { + T operator()(V &v) { + return v.pnode; + } +}; + +// specialization for SiActionNodeEx_t** +template struct value_member { + T operator()(V &v) { + return &v.pnode; + } +}; + +// specialization for string_t +template struct value_member { + T operator()(V &v) { + return v.string; + } +}; + +// specialization for string_t* +template struct value_member { + T operator()(V &v) { + return &v.string; + } +}; + +// specialization for cstr_t +template struct value_member { + T operator()(V &v) { + return v.cstr_; + } +}; + +// specialization for cstr_t* +template struct value_member { + T operator()(V &v) { + return &v.cstr_; + } +}; + +// specialization for imagearray_t +template struct value_member { + T operator()(V &v) { + return v.imagearray; + } +}; + +// specialization for imagearray_t* +template struct value_member { + T operator()(V &v) { + return &v.imagearray; + } +}; + +template struct cast_value { + T operator()(V &value) { + switch (value.type) { + case bool_type: + return static_cast(value.b); + + case long_type: + return static_cast(value.l); + + case float_type: + return static_cast(value.f); + + case double_type: + return static_cast(value.d); + + default: + return static_cast(0); + } + } +}; + +// Specialization for bool +template struct cast_value { + bool operator()(V &value) { + switch (value.type) { + case bool_type: + return value.b != 0; + + case long_type: + return value.l != 0; + + case float_type: + return value.f != 0.0f; + + case double_type: + return value.d != 0.0; + + default: + return false; + } + } +}; +} // namespace navlib +#endif /* NAVLIB_TEMPLATES_H_INCLUDED_ */ diff --git a/thirdparty/3DConnexion/inc/navlib/navlib_types.h b/thirdparty/3DConnexion/inc/navlib/navlib_types.h new file mode 100644 index 00000000..851a80b7 --- /dev/null +++ b/thirdparty/3DConnexion/inc/navlib/navlib_types.h @@ -0,0 +1,1995 @@ +#ifndef NAVLIB_TYPES_H_INCLUDED_ +#define NAVLIB_TYPES_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File History +// +// $Id: navlib_types.h 19945 2023-01-26 07:48:01Z mbonk $ +// +// 01/23/14 MSB Initial design +// +// +// ************************************************************************************************* +// File Description +// +// This header file describes the variable types used in the 3dconnexion navlib interface. +// +// ************************************************************************************************* +// +#include + +#if (defined(_MSC_VER) && _MSC_VER < 1600) +typedef __int8 int8_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#if _WIN64 +typedef unsigned __int64 size_t; +#else +typedef unsigned int size_t; +#endif +#else +#include +#endif + +// 3dxware +#include + +// stdlib +#include + +#if __cplusplus +#include +#include +#include +#include +#if defined(_MSC_VER) && (_MSC_VER <= 1800) +#include +#endif +/// +/// Contains the navigation library API types and functions +/// +NAVLIB_BEGIN_ + +/// +/// Defines a type of object to be thrown as exception. It reports errors that result from attempts +/// to convert a value to an incompatible type. +/// +class conversion_error : public std::logic_error { + typedef std::logic_error Mybase; + +public: + + explicit conversion_error(const std::string &message) + : Mybase(message.c_str()) { // construct from message string + } + + explicit conversion_error(const char *message) + : Mybase(message) { // construct from message string + } +}; +NAVLIB_END_ +#endif //__cplusplus + +NAVLIB_BEGIN_ +/// +/// Describes the type of a property as well as the type of the value passed in value_t +/// +/// +/// Generally no type conversion is performed. So that if a property is defined as being of +/// float_type then the navlib will expect the value_t structure to contain a value with +/// type=float_type. +/// +typedef enum propertyTypes { + /// + /// . + /// + auto_type = -2, + /// + /// The type is unknown. + /// + unknown_type = -1, + /// + /// *. + /// + voidptr_type = 0, + /// + /// . + /// + bool_type, + /// + /// . + /// + long_type, + /// + /// . + /// + float_type, + /// + /// . + /// + double_type, + /// + /// . + /// + point_type, + /// + /// . + /// + vector_type, + /// + /// . + /// + matrix_type, + /// + /// . + /// + string_type, + /// + /// const *. + /// + actionnodeexptr_type, + /// + /// . + /// + plane_type, + /// + /// . + /// + box_type, + /// + /// . + /// + frustum_type, + /// + /// . + /// + cstr_type, + /// + /// . + /// + imagearray_type +} propertyType_t; + +/// +/// Type used to identify which property is being addressed. +/// +typedef const char *property_t; + +/// +/// Describes the available property access +/// +typedef enum propertyAccess { + /// + /// Property cannot be accessed. + /// + eno_access = 0, + /// + /// Property can be changed. + /// + ewrite_access, + /// + /// Property is read only. + /// + eread_access, + /// + /// Property can be read and written to. + /// + eread_write_access +} propertyAccess_t; + +/// +/// Describes a property's type and required access. +/// +/// +/// This defines the value of used in to pass the +/// property's value between the client and the navlib. +/// +typedef struct { + /// + /// The name of the property. + /// + property_t name; + /// + /// The type of the value stored by the property. + /// + propertyType_t type; + /// + /// The access the client interface exposes to the navlib server + /// + propertyAccess_t client; +} propertyDescription_t; + +/// +/// Type used to store bool values in +/// +typedef uint32_t bool_t; + +/// +/// Type used for the client defined parameter used in and . +/// +typedef uint64_t param_t; + +#if defined(NAVLIB_USE_NON_STANDARD_STRUCT_EXTENSION) +#if defined(_MSC_VER) +#pragma message("warning: The non-standard anonymous structure definitions are deprecated and will be removed in the next release.") +#else +#warning The non-standard anonymous structure definitions are deprecated and will be removed in the next release. +#endif + +/// +/// Represents an x-, y-, and z-coordinate location in 3-D space. +/// +typedef struct point { + union { + struct { + double x, y, z; + }; + double coordinates[3]; + }; + +#if __cplusplus +private: + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + default: + throw std::out_of_range("index i"); + } + } + +public: + double operator[](size_t i) const { + return get_value(*this, i); + } + + double &operator[](size_t i) { + return get_value(*this, i); + } + + typedef const double (&const_array)[3]; + operator const_array() const { + return coordinates; + } +#endif +} point_t; + +/// +/// Represents a displacement in 3-D space. +/// +typedef struct vector { + union { + struct { + double x, y, z; + }; + double components[3]; + }; + +#if __cplusplus +private: + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + default: + throw std::out_of_range("index i"); + } + } + +public: + double operator[](size_t i) const { + return get_value(*this, i); + } + + double &operator[](size_t i) { + return get_value(*this, i); + } + + typedef const double (&const_array)[3]; + operator const_array() const { + return components; + } +#endif +} vector_t; + +/// +/// Represents a plane in 3-D space. +/// +/// The plane is defined as a unit normal to the plane and the +/// distance of the plane to the origin along the normal. A p on the plane +/// satisfies the vector equation: n.(p - point_t(0,0,0)) + d = 0; +typedef struct plane { + union { + struct { + double x, y, z, d; + }; + struct { + vector_t n; + double d_; + }; + double equation[4]; + }; + +#if __cplusplus +private: + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + case 3: + return t.d; + default: + throw std::out_of_range("index i"); + } + } + +public: + double operator[](size_t i) const { + return get_value(*this, i); + } + + double &operator[](size_t i) { + return get_value(*this, i); + } + + typedef const double (&const_array)[4]; + operator const_array() const { + return equation; + } +#endif +} plane_t; + +/// +/// Represents a 3D-rectangle volume. +/// +/// +/// The volume is described by two diagonally opposing locations. +/// contains the coordinates with the smallest values. +/// +typedef struct box { + union { + struct { + double min_x, min_y, min_z, max_x, max_y, max_z; + }; + struct { + point_t min, max; + }; + double b[6]; + }; + +#if __cplusplus + /// + /// checks whether the box is empty. + /// + /// + bool empty() const { + return (max.x < min.x || max.y < min.y || max.z < min.z); + } + + typedef const double (&const_array)[6]; + operator const_array() const { + return b; + } +#endif +} box_t; + +/// +/// Represents a frustum. +/// +typedef struct frustum { + union { + struct { + double left, right, bottom, top, nearVal, farVal; + }; + double parameters[6]; + }; +#if __cplusplus + typedef const double (&const_array)[6]; + operator const_array() const { + return parameters; + } +#endif +} frustum_t; + +/// +/// Represents a 4 x 4 matrix used for transformations in 3-D space. +/// +typedef struct matrix { + union { + struct { + double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; + }; + double m[16]; + double m4x4[4][4]; + }; +#if __cplusplus +private: + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.m00; + case 1: + return t.m01; + case 2: + return t.m02; + case 3: + return t.m03; + case 4: + return t.m10; + case 5: + return t.m11; + case 6: + return t.m12; + case 7: + return t.m13; + case 8: + return t.m20; + case 9: + return t.m21; + case 10: + return t.m22; + case 11: + return t.m23; + case 12: + return t.m30; + case 13: + return t.m31; + case 14: + return t.m32; + case 15: + return t.m33; + default: + throw std::out_of_range("index i"); + } + } + + template static auto &get_value(T &&t, size_t row, size_t column) { + return get_value(std::forward(t), row * 4 + column); + } + + public: + double* begin() { + return &m00; + } + + double* end() { + return &m[16]; + } + + double operator[](size_t i) const { + return get_value(*this, i); + } + + double &operator[](size_t i) { + return get_value(*this, i); + } + + double operator()(size_t row, size_t column) const { + return get_value(*this, row, column); + // return get_value(*this, row * 4 + column); + } + + double &operator()(size_t row, size_t column) { + return get_value(*this, row, column); + // return get_value(*this, row * 4 + column); + } + + typedef const double (&const_array)[16]; + operator const_array() const { + return m; + } +#endif +} matrix_t; +#else +/// +/// Represents an x-, y-, and z-coordinate location in 3-D space. +/// +typedef struct point { + double x, y, z; + +#if __cplusplus +private: +#if !defined(_MSC_VER) || (_MSC_VER > 1800) + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + default: + throw std::out_of_range("index i"); + } + } +#else + template static double get_value(const T &t, size_t i) { + return get_value(const_cast(t), i); + } + + template static double &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + default: + throw std::out_of_range("index i"); + } + } +#endif + +public: + /// + /// Allows members to be accessed using array notation. + /// + /// Index of the member. + /// The value of the member. + /// The index of x=0, y=1, z=2. + double operator[](size_t i) const { + return get_value(*this, i); + } + + /// + /// Allows members to be accessed using array notation. + /// + /// Index of the member. + /// A reference to the member. + /// The index of x=0, y=1, z=2. + double &operator[](size_t i) { + return get_value(*this, i); + } +#endif +} point_t; + +/// +/// Represents a displacement in 3-D space. +/// +typedef struct vector { + double x, y, z; + +#if __cplusplus +private: +#if !defined(_MSC_VER) || (_MSC_VER > 1800) + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + default: + throw std::out_of_range("index i"); + } + } +#else + template static double get_value(const T &t, size_t i) { + return get_value(const_cast(t), i); + } + + template static double &get_value(T &t, size_t i){ + switch (i) { + case 0: + return t.x; + case 1: + return t.y; + case 2: + return t.z; + default: + throw std::out_of_range("index i"); + } + } +#endif + +public: + /// + /// Allows members to be accessed using array notation. + /// + /// Index of the member. + /// The value of the member. + /// The index of x=0, y=1, z=2. + double operator[](size_t i) const { + return get_value(*this, i); + } + + /// + /// Allows members to be accessed using array notation. + /// + /// Index of the member. + /// A reference to the member. + /// The index of x=0, y=1, z=2. + double &operator[](size_t i) { + return get_value(*this, i); + } +#endif +} vector_t; + +/// +/// Represents a plane in 3-D space. +/// +/// The plane is defined as a unit normal to the plane and the +/// distance of the plane to the origin along the normal. A p on the plane +/// satisfies the vector equation: n.(p - point_t(0,0,0)) + d = 0; +typedef struct plane { + vector_t n; + double d; +} plane_t; + +/// +/// Represents a 3D-rectangle volume. +/// +/// +/// The volume is described by two diagonally opposing locations. +/// contains the coordinates with the smallest values. +/// +typedef struct box { + point_t min, max; +#if __cplusplus + /// + /// checks whether the box is empty. + /// + /// + bool empty() const { + return (max.x < min.x || max.y < min.y || max.z < min.z); + } +#endif +} box_t; + +/// +/// Represents a frustum. +/// +typedef struct frustum { + double left, right, bottom, top, nearVal, farVal; +} frustum_t; + +/// +/// Represents a 4 x 4 matrix used for transformations in 3-D space. +/// +typedef struct matrix { + double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; + +#if __cplusplus +private: +#if !defined(_MSC_VER) || (_MSC_VER > 1800) + template static auto &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.m00; + case 1: + return t.m01; + case 2: + return t.m02; + case 3: + return t.m03; + case 4: + return t.m10; + case 5: + return t.m11; + case 6: + return t.m12; + case 7: + return t.m13; + case 8: + return t.m20; + case 9: + return t.m21; + case 10: + return t.m22; + case 11: + return t.m23; + case 12: + return t.m30; + case 13: + return t.m31; + case 14: + return t.m32; + case 15: + return t.m33; + default: + throw std::out_of_range("index i"); + } + } +#else + template static double get_value(const T &t, size_t i) { + return get_value(const_cast(t), i); + } + + template static double &get_value(T &t, size_t i) { + switch (i) { + case 0: + return t.m00; + case 1: + return t.m01; + case 2: + return t.m02; + case 3: + return t.m03; + case 4: + return t.m10; + case 5: + return t.m11; + case 6: + return t.m12; + case 7: + return t.m13; + case 8: + return t.m20; + case 9: + return t.m21; + case 10: + return t.m22; + case 11: + return t.m23; + case 12: + return t.m30; + case 13: + return t.m31; + case 14: + return t.m32; + case 15: + return t.m33; + default: + throw std::out_of_range("index i"); + } + } +#endif + +public: + /// + /// Allows members to be accessed using array notation. + /// + /// Index of the member. + /// The value of the member. + /// The index of an .mxy is calculated from 4*x+y. + double operator[](size_t i) const { + return get_value(*this, i); + } + + /// + /// Allows members to be accessed using array notation. + /// + /// Index of the member. + /// A reference to the member. + /// The index of an .mxy is calculated from 4*x+y. + double &operator[](size_t i) { + return get_value(*this, i); + } + + /// + /// Allows member access using matrix notation. + /// + /// The matrix row index + /// The matrix column index + /// The value of the member. + double operator()(size_t row, size_t column) const { + return (*this)[row * 4 + column]; + } + + /// + /// Allows member access using matrix notation. + /// + /// The matrix row index + /// The matrix column index + /// A reference to the member. + double &operator()(size_t row, size_t column) { + return (*this)[row * 4 + column]; + } + + /// + /// Random access iterator for the matrix. + /// + struct iterator : public std::allocator_traits> { + using base_type = std::allocator_traits>; + using reference = base_type::value_type&; + using difference_type = base_type::difference_type; + using iterator_category = std::random_access_iterator_tag; + + explicit iterator(struct matrix &m, size_type index = 0) : m_container(m), m_index(index){ + } + + iterator(const iterator &iter) : m_container(iter.m_container), m_index(iter.m_index) { + } + + ~iterator() { + } + + iterator &operator=(const iterator &other) { + m_container = other.m_container; + m_index = other.m_index; + return *this; + } + + bool operator==(const iterator &other) const { + return std::addressof(m_container) == std::addressof(other.m_container) && + m_index == other.m_index; + } + + bool operator!=(const iterator &other) const { + return std::addressof(m_container) != std::addressof(other.m_container) || + m_index != other.m_index; + } + + iterator &operator+(difference_type offset) { + m_index += offset / sizeof(double); + return *this; + } + + iterator &operator++() { + ++m_index; + return *this; + } + + reference operator*() NOEXCEPT { + return m_container[m_index]; + } + + pointer operator->() NOEXCEPT { + return &m_container[m_index]; + } + + protected: + struct matrix &m_container; + size_type m_index; + }; + + /// + /// Returns an to the beginning. + /// + /// An to the first element of the matrix. + iterator begin() { + return iterator(*this, 0); + } + + /// + /// Returns an to the end. + /// + /// An to the element following the last element of the + /// matrix. + iterator end() { + return iterator(*this, 16); + } +#endif +} matrix_t; +#endif + +/// +/// Represents a writable string. +/// +typedef struct { + char *p; + size_t length; +} string_t; + +/// +/// Represents a read only string. +/// +typedef struct { + const char *p; + size_t length; +} cstr_t; + +/// +/// Represents an array of pointers. +/// +typedef struct { + const SiImage_t *p; + size_t count; +} imagearray_t; +NAVLIB_END_ +#if __cplusplus +#include +#endif +NAVLIB_BEGIN_ + +/// +/// Variant type used to transfer property values in the interface. +/// +/// can hold one of the types defined in +/// . +typedef struct value { + /// + /// The of the contained value. + /// + propertyType_t type; + /// + /// The contained data value. + /// + union { + void *p; + bool_t b; + long l; + float f; + double d; + point_t point; + vector_t vector; + plane_t plane; + box_t box; + frustum_t frustum; + matrix_t matrix; + const SiActionNodeEx_t *pnode; + string_t string; + cstr_t cstr_; + imagearray_t imagearray; + }; + +#if __cplusplus + /// + /// Instantiates an . + /// + /// + /// values can be assigned to but not read. The data assignment also + /// assigns the type. + /// + value() : type(auto_type) { + } + /// + /// Instantiates a containing a + /// *. + /// + /// The * to assign to the + /// struct. + value(void *aVoidPointer) : type(voidptr_type), p(aVoidPointer) { + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(bool aBool) : type(bool_type), b(static_cast(aBool)) { + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(bool_t aBool) : type(bool_type), b(aBool) { + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(long aLong) : type(long_type), l(aLong) { + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(float aFloat) : type(float_type), f(aFloat) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(double aDouble) : type(double_type), d(aDouble) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(const point_t &aPoint) : type(point_type), point(aPoint) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(const vector_t &aVector) : type(vector_type), vector(aVector) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(const plane_t &aPlane) : type(plane_type), plane(aPlane) { + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(const box_t &aBox) : type(box_type), box(aBox) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(const frustum_t &aFrustum) : type(frustum_type), frustum(aFrustum) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(const matrix_t &aMatrix) : type(matrix_type), matrix(aMatrix) { + } + /// + /// Instantiates a containing a + /// *. + /// + /// The * to assign to the + /// struct. + value(const SiActionNodeEx_t *aNode) : type(actionnodeexptr_type), pnode(aNode) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The to assign to the + /// struct. + value(string_t &aString) : type(string_type), string(aString) { + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(cstr_t &cstr) : type(cstr_type), cstr_(cstr) { + } + /// + /// Instantiates a containing a + /// . + /// + /// The * to assign to the + /// struct. + /// The length of the string. + value(char *aString, size_t length) : type(string_type) { + string.length = length; + string.p = aString; + } + /// + /// Instantiates a containing a . + /// + /// The null terminated * to assign to the + /// struct. + value(const char *aString) : type(cstr_type) { + cstr_.p = aString; + cstr_.length = aString != nullptr ? strlen(aString) + 1 : 0; + } + /// + /// Instantiates a containing a . + /// + /// The to assign to the + /// struct. + value(const std::string &aString) : type(cstr_type) { + cstr_.p = aString.c_str(); + cstr_.length = aString.length() + 1; + } + /// + /// Instantiates an containing a + /// . + /// + /// The to assign to the + /// struct. + value(const imagearray_t &images) : type(imagearray_type), imagearray(images) { + } + /// + /// Instantiates an containing a + /// . + /// + /// The * to assign to the + /// struct. + /// The image count. + value(const SiImage_t *images, size_t count) : type(imagearray_type) { + imagearray.count = count; + imagearray.p = images; + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator bool() const { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator bool() { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator bool_t() const { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator bool_t() { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// An representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator int() const { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// An representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator int() { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator long() const { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator long() { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator float() const { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator float() { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator double() const { + return cast_value()(*this); + } + + /// + /// Conversion operator + /// + /// A representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator double() { + return cast_value()(*this); + } + + /// + /// Template to enable implicit T& conversion. + /// + template operator T &() { + return conversion_operator(); + } + + /// + /// Template to enable implicit T const & conversion. + /// + template operator T const &() const { + return cast_value()(*this); + } + + /// + /// Template function to convert a value with type checking. + /// + /// The inner member variable of the union corresponding to the + /// type. + /// Invalid conversion attempted. + template T conversion_operator() { + if (std::is_reference::value) { + if (type == auto_type) { + type = property_type::type; + } + } + + if (type != property_type::type) { + if ((type == float_type && property_type::type == double_type) || + (type == double_type && property_type::type == float_type)) { + type = property_type::type; + } else { + throw_conversion_error(property_type::name); + } + } + + return value_member::type>()(*this); + } + + /// + /// Template function to convert a value with type checking. + /// + /// The inner member variable of the union corresponding to the + /// type. + /// Invalid conversion attempted. + template T conversion_operator() const { + if (type != property_type::type) { + throw_conversion_error(property_type::name); + } + + return value_member::type>()(*this); + } + + /// + /// Conversion / accessor operator. + /// + /// A *& to the internal value. + /// Throws if the conversion is not + /// possible. + operator void *&() { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator point_t &() { + return conversion_operator(); + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const point_t &() const { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator vector_t &() { + return conversion_operator(); + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const vector_t &() const { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator plane_t &() { + return conversion_operator(); + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const plane_t &() const { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator box_t &() { + return conversion_operator(); + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const box_t &() const { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator frustum_t &() { + return conversion_operator(); + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const frustum_t &() const { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator matrix_t &() { + return conversion_operator(); + } + + /// + /// Conversion. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const matrix_t &() const { + return conversion_operator(); + } + + typedef const SiActionNodeEx_t *cpSiActionNodeEx_t; + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator cpSiActionNodeEx_t &() { + return conversion_operator(); + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator imagearray_t &() { + return conversion_operator(); + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const imagearray_t &() const { + return conversion_operator(); + } + + /// + /// Throws a exception. + /// + /// The attempted type conversion. + /// Invalid conversion attempted. + void throw_conversion_error(const std::string &target_type) const { + std::ostringstream stream; + stream << "Invalid conversion from value type " << type << " to " << target_type.c_str(); + throw NAVLIB_ conversion_error(stream.str().c_str()); + } + + ////////////////////////////////////////////////////////////////// + // Strings - treat string_t and cstr_t the same to avoid confusion + + /// + /// Conversion operator. + /// + /// A const* representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const char *() const { + if (type != cstr_type && type != string_type) { + throw_conversion_error("string_type"); + } + return type == string_type ? string.p : cstr_.p; + } + + /// + /// Conversion operator. + /// + /// A const* representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const string_t *() const { + if (type != cstr_type && type != string_type) { + throw_conversion_error("cstr_type"); + } + return &string; + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const string_t &() const { + if (type != cstr_type && type != string_type) { + throw_conversion_error("cstr_type"); + } + return string; + } + + /// + /// Conversion / accessor operator. + /// + /// A & representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator string_t &() { + if (type == auto_type) { + type = string_type; + } + if (type != cstr_type && type != string_type) { + throw_conversion_error("string_type"); + } + return string; + } + + /// + /// Conversion operator. + /// + /// A const* representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const cstr_t *() const { + if (type != cstr_type && type != string_type) { + throw_conversion_error("cstr_type"); + } + return &cstr_; + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const cstr_t &() const { + if (type != cstr_type && type != string_type) { + throw_conversion_error("cstr_type"); + } + return cstr_; + } + + /// + /// Conversion / accessor operator. + /// + /// A & to the internal value. + /// Throws if the conversion is not + /// possible. + operator cstr_t &() { + if (type == auto_type) { + type = cstr_type; + } + if (type != cstr_type && type != string_type) { + throw_conversion_error("cstr_type"); + } + return cstr_; + } + + /// + /// Conversion operator. + /// + /// A const* representation of the internal + /// value. + /// Throws if the conversion is + /// not possible. + operator const SiActionNodeEx_t *() const { + if (type != actionnodeexptr_type) { + throw_conversion_error("actionnodeexptr_type"); + } + return pnode; + } + + /// + /// Conversion operator. + /// + /// A const& representation of the internal + /// value. + /// Throws if the conversion is + /// not possible. + operator const SiActionNodeEx_t &() const { + if (type != actionnodeexptr_type) { + throw_conversion_error("actionnodeexptr_type"); + } + return *pnode; + } + + /// + /// Conversion operator. + /// + /// A const* representation of the internal value. + /// Throws if the conversion is not + /// possible. + operator const imagearray_t *() const { + if (type != imagearray_type) { + throw_conversion_error("imagearray_type"); + } + return &imagearray; + } + + // Assignment operators + + /// + /// Assignment operator. + /// + /// The * to assign to the struct. + /// A & to this struct. + /// Assigns a * to the internal value and sets + /// to . + struct value &operator=(void *aVoidPointer) { + p = aVoidPointer; + type = voidptr_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(bool aBool) { + b = static_cast(aBool); + type = bool_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(long aLong) { + l = aLong; + type = long_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(float aFloat) { + f = aFloat; + type = float_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(double aDouble) { + d = aDouble; + type = double_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + /// + struct value &operator=(const point_t &aPoint) { + point = aPoint; + type = point_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + /// + struct value &operator=(const plane_t &aPlane) { + plane = aPlane; + type = plane_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the struct. + /// + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(const box_t &aBox) { + box = aBox; + type = box_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(const frustum_t &aFrustum) { + frustum = aFrustum; + type = frustum_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(const matrix_t &aMatrix) { + matrix = aMatrix; + type = matrix_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The const* to assign to the + /// struct. + /// A & to this struct. + /// Assigns a * to the internal value and sets + /// to . + struct value &operator=(const SiActionNodeEx_t *aNode) { + pnode = aNode; + type = actionnodeexptr_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The const& to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(const string_t &aString) { + string = aString; + type = string_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The const& to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(const cstr_t &cstr) { + cstr_ = cstr; + type = cstr_type; + return *this; + } + + /// + /// Assignment operator. + /// + /// The const& to assign to the + /// struct. + /// A & to this struct. + /// Assigns a to the internal value and sets + /// to . + struct value &operator=(const imagearray_t &images) { + imagearray = images; + type = imagearray_type; + return *this; + } +#endif // __cplusplus +} value_t; + +/// +/// The prototype of the function the navlib invokes to retrieve the value of a property. +/// +/// Value passed in in . +/// +/// Value passed in in . +/// +/// Pointer to a for the value of the property. +/// A navlib result code. . +/// When the application services the function call it sets the current value and the type +/// of the property into the variant. +typedef long(__cdecl *fnGetProperty_t)(const param_t param, const property_t name, value_t *value); + +/// +/// The prototype of the function the navlib invokes to set the value of a property. +/// +/// Value passed in in . +/// +/// Value passed in in . +/// +/// A containing the value of the property. +/// A navlib result code. . +/// When the application services the function call it sets its current value of the +/// property from the variant. +typedef long(__cdecl *fnSetProperty_t)(const param_t param, const property_t name, + const value_t *value); + +/// +/// Represents a client property accessor and mutator. +/// +/// +/// +/// The application passes an array of accessor_t structures in to define the +/// interface that the navlib can use to query or apply changes to a client property. Depending on +/// the user/3d mouse input the navlib will query the application for the values of properties +/// needed to fulfill the requirements of the navigation model the user has invoked and when a new +/// camera position has been calculated set the corresponding properties. +/// +/// +/// To retrieve the value of a property the navlib will call the fnGet member of the property's +/// accessor_t, passing in param, the name of the property as well as a pointer to a value_t. +/// Similarly, to apply a change to a property the navlib will invoke the fnSet member of the +/// property's accessor_t, passing in the param, property name and a pointer to a value_t. +/// +/// +/// If either of fnSet or fnGet is null, then the property is respectively read- or write-only. +/// +/// +typedef struct tagAccessor { + /// + /// The name of the property + /// + property_t name; + /// + /// The function the navlib calls to retrieve the property's value from the client application. + /// + fnGetProperty_t fnGet; + /// + /// The function the navlib calls to set the property's value in the client application. + /// + fnSetProperty_t fnSet; + /// + /// The value to pass to the and + /// functions as the first parameter. + /// + param_t param; +} accessor_t; + +/// +/// Type used for navlib handles. +/// +typedef uint64_t nlHandle_t; + +/// +/// Configuration options +/// +typedef enum nlOptions { + /// + /// No options. + /// + none = 0, + /// + /// Use non-queued message passing. + /// + nonqueued_messages = 1, + /// + /// Matrices are stored in row major order. + /// + /// + /// The default is column major order. + /// + row_major_order = 2 +} nlOptions_t; + +/// +/// Structure for navlib initialization options passed in the . +/// +typedef struct tagNlCreateOptions { + /// + /// Size of this structure. + /// + uint32_t size; + /// + /// true is to use multi-threading, false for single-threaded. + /// + /// The default is false (single-threaded). +#if __cplusplus + bool bMultiThreaded; +#else + int8_t bMultiThreaded; +#endif + /// + nlOptions_t options; +} nlCreateOptions_t; + +#ifndef TDX_ALWAYS_INLINE +#ifdef _MSC_VER +#define TDX_ALWAYS_INLINE __forceinline +#else +#define TDX_ALWAYS_INLINE __attribute__((always_inline)) inline +#endif +#endif +/// +/// Makes a result code in the navlib facility. +/// +/// The error code. +/// A result code in the navlib facility. +TDX_ALWAYS_INLINE long make_result_code(unsigned long x) { +#if __cplusplus + return static_cast(x) <= 0 + ? static_cast(x) + : static_cast(((x)&0x0000FFFF) | (FACILITY_NAVLIB << 16) | 0x80000000); +#else + return (long)x <= 0 ? (long)x : (long)(((x)&0x0000FFFF) | (FACILITY_NAVLIB << 16) | 0x80000000); +#endif +} + +#if __cplusplus +/// +/// Contains error codes used by the navlib. +/// +namespace navlib_errc { +#endif +/// +/// Error codes used in the navlib facility. +/// +enum navlib_errc_t { + /// + /// Error. + /// + error = EIO, + /// + /// Already connected. + /// + already_connected = EISCONN, + /// + /// The function is not supported. + /// + function_not_supported = ENOSYS, + /// + /// The argument is invlaid. + /// + invalid_argument = EINVAL, + /// + /// No data is available. + /// + no_data_available = ENODATA, + /// + /// Not enough memory. + /// + not_enough_memory = ENOMEM, + /// + /// The buffer is too small. + /// + insufficient_buffer = ENOBUFS, + /// + /// THe operation is invalid in the current context. + /// + invalid_operation = EPERM, + /// + /// Sorry, not allowed. + /// + permission_denied = EACCES, + /// + /// The property does not exists. + /// + property_not_found = 0x201, + /// + /// The function does not exist. + /// + invalid_function = 0x202, +}; +#if __cplusplus +} // namespace navlib::navlib_errc:: +#endif + +NAVLIB_END_ + +#endif /* NAVLIB_TYPES_H_INCLUDED_ */ diff --git a/thirdparty/3DConnexion/inc/siappcmd_types.h b/thirdparty/3DConnexion/inc/siappcmd_types.h new file mode 100644 index 00000000..52fa9781 --- /dev/null +++ b/thirdparty/3DConnexion/inc/siappcmd_types.h @@ -0,0 +1,190 @@ +#ifndef siappcmd_types_H_INCLUDED_ +#define siappcmd_types_H_INCLUDED_ +// +// ------------------------------------------------------------------------------------------------- +// This source file is part of the Avogadro project. +// +// Copyright (c) 2014-2023 3Dconnexion. +// +// This source code is released under the 3-Clause BSD License, (see "LICENSE"). +// ------------------------------------------------------------------------------------------------- +// +// +// ************************************************************************************************* +// File Description +// +// This header file describes the variable types used in the 3dconnexion interface that allows a +// user to assign an arbitrary action to a 3dconnexion device button. +// +// Data structures are described in detail below. +// +// ************************************************************************************************* +// +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_MSC_VER) && (_MSC_VER<1600) + typedef unsigned __int32 uint32_t; + typedef unsigned __int8 uint8_t; +#if _WIN64 + typedef unsigned __int64 uintptr_t; +#else + typedef unsigned int uintptr_t; +#endif +#else +#include +#include +#endif + + typedef enum siActionNodeType_e + { + SI_ACTIONSET_NODE = 0 + , SI_CATEGORY_NODE + , SI_ACTION_NODE + } SiActionNodeType_t; + + /*------------------------------------+--------------------------------------- + + SiActionNodeEx_t + + The application passes a pointer to a structure of type SiActionNodeEx_t to + the function SiAppCmdWriteActionSet + + A set of actions is composed of a linked list of SiActionNodeEx_t structures. + Sibling nodes are linked by the next field of the structure and child nodes + by the children field. The root node of the tree represents the name of the + action set while the leaf nodes of the tree represent the actions that can be + assigned to buttons and invoked by the user. The intermediate nodes represent + categories and sub-categories for the actions. An example of this would be the + menu item structure in a menu bar. The menus in the menu bar would be + represented by the SiActionNodeEx_t structures with type SI_CATEGORY_NODE pointed + to by each successively linked next field and the first menu item of each menu + represented by the structure pointed to by their child fields (the rest of the + menu items in each menu would again be linked by the next fields). + + size + The size field must always be the byte size of siActionNodeEx_s + + type + The type field specifies one of the following values. + SI_ACTIONSET_NODE + SI_CATEGORY_NODE + SI_ACTION_NODE + + The root node (and only the root node) of the tree always has type + SI_ACTIONSET_NODE. Only the leaf nodes of the tree have type SI_ACTION_NODE. + All intermediate nodes have type SI_CATEGORY_NODE. + + id + The id field specifies a UTF8 string identifier for the action set, + category, or action represented by the node. The field is always non-NULL. + This string needs to remain constant across application sessions and more + or less constant across application releases. The id is used by the + application to identify an action. + + label + The label field specifies a UTF8 localized/internationalized name + for the action set, category, or action represented by the node. The label + field can be NULL for the root and intermediate category nodes that are not + explicitly presented to users. All leaf (action) and intermediate nodes + containing leaf nodes have non-NULL labels. If the application only has a + single action tree set, then the label of the root (context) node can also + be NULL. + + description + The description field specifies a UTF8 localized/internationalized tooltip + for the action set, category, or action represented by the node. The description + field can be NULL for the root and intermediate category nodes that are not + explicitly presented to users. Leaf (action) nodes should have non-NULL descriptions. + + --------------------------------------+-------------------------------------*/ + typedef struct siActionNodeEx_s + { + uint32_t size; + SiActionNodeType_t type; + struct siActionNodeEx_s *next; + struct siActionNodeEx_s *children; + const char *id; + const char *label; + const char *description; + } SiActionNodeEx_t; + + /*------------------------------------+--------------------------------------- + + SiImage_t + + The application passes a pointer to an array of type SiImage_t to + the function SiAppCmdWriteActionImages + + size + The size field specifies the size of the SiImage_t type in bytes. + + id + The id field specifies a UTF8 string identifier for the image. The field + is always non-NULL. This string needs to remain constant across application + sessions and more or less constant across application releases. + The id is used by the application to identify the image. To associate an + image with a command the id needs to be identical to the value of the + SiActionNodeEx_t::id of the action. + + siImageData_s::size + The siImageData_s::size field specifies the size of the data pointed to + by the siImageData_s::data field in bytes. + + siImageData_s::data + The image field contains a pointer to the image. The image may be in coded + in any recognizable format. + + --------------------------------------+-------------------------------------*/ + typedef enum eSiImageType { + e_none = 0 + , e_image_file + , e_resource_file + , e_image + , e_glyph + } SiImageType_t; + + struct siResource_s { + const char *file_name; + const char *id; + const char *type; + uint32_t index; + }; + + struct siImageFile_s { + const char *file_name; + uint32_t index; + }; + + struct siImageData_s { + const uint8_t *data; + uintptr_t size; + uint32_t index; + }; + + struct siImageGlyph_s { + const char* font_family; + const wchar_t* glyphs; + const uint32_t* reserved1; + uint32_t reserved2; + }; + + typedef struct siImage_s + { + uint32_t size; + SiImageType_t type; + const char *id; + union { + struct siResource_s resource; + struct siImageFile_s file; + struct siImageData_s image; + struct siImageGlyph_s glyph; + }; + } SiImage_t; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* siappcmd_types_H_INCLUDED_ */ \ No newline at end of file diff --git a/thirdparty/3DConnexion/src/navlib_load.cpp b/thirdparty/3DConnexion/src/navlib_load.cpp new file mode 100644 index 00000000..26948f59 --- /dev/null +++ b/thirdparty/3DConnexion/src/navlib_load.cpp @@ -0,0 +1,12 @@ +/****************************************************************************** + This source file is part of the Avogadro project. + + Copyright (c) 2014-2023 3Dconnexion. + + This source code is released under the 3-Clause BSD License, (see "LICENSE"). +******************************************************************************/ + +extern "C" { + extern long NlLoadLibrary(); + extern const long NlErrorCode = NlLoadLibrary(); +} diff --git a/thirdparty/3DConnexion/src/navlib_stub.c b/thirdparty/3DConnexion/src/navlib_stub.c new file mode 100644 index 00000000..8b5d98d7 --- /dev/null +++ b/thirdparty/3DConnexion/src/navlib_stub.c @@ -0,0 +1,171 @@ +/****************************************************************************** + This source file is part of the Avogadro project. + + Copyright (c) 2014-2023 3Dconnexion. + + This source code is released under the 3-Clause BSD License, (see "LICENSE"). +******************************************************************************/ + +/** + * @file navlib_stub.c + * @brief interface routines to the navlib library routines. + */ + +/*----------------------------------------------------------------------------- + * The module contains interface routines to the navlib library routines + * contained in the associated Dynamic Link Library. The DLL is loaded + * explicitly when NlLoadLibrary is invoked. When the DLL is loaded, the + * initialization routine finds the addresses of the routines that it exposes + * and allows them to be used in this code. + */ + +#if _WIN32 + +// windows +#include +#include +#elif __APPLE__ +#include +#include +#include +#endif + +#ifndef EISCONN +#define EISCONN 113 +#define ENOBUFS 119 +#define ENODATA 120 +#define EOPNOTSUPP 130 +#endif + +// navlib +#include + +/* DLL library name */ +#ifdef _WIN32 +static const char *TheLibrary = "TDxNavLib"; +#elif __APPLE__ +static const char *TheLibrary = "/Library/Frameworks/3DconnexionNavlib.framework/3DconnexionNavlib"; +#endif + +/* Names of functions contained in DLL; used to find their addresses at load time */ +static const char *cNlCreate = "NlCreate"; +static const char *cNlClose = "NlClose"; +static const char *cNlReadValue = "NlReadValue"; +static const char *cNlWriteValue = "NlWriteValue"; +static const char *cNlGetType = "NlGetType"; + +typedef long(__cdecl *PFN_NLCREATE)(nlHandle_t *pnh, const char *appname, + const accessor_t accessors[], size_t accessor_count, + nlCreateOptions_t const *options); +typedef long(__cdecl *PFN_NLCLOSE)(nlHandle_t nh); +typedef long(__cdecl *PFN_NLREADVALUE)(nlHandle_t nh, property_t name, value_t *value); +typedef long(__cdecl *PFN_NLWRITEVALUE)(nlHandle_t nh, property_t name, const value_t *value); +typedef propertyType_t(__cdecl *PFN_NLGETTYPE)(property_t name); + +/* Function pointers to functions in DLL */ +static PFN_NLCREATE pfnNlCreate = NULL; +static PFN_NLCLOSE pfnNlClose = NULL; +static PFN_NLREADVALUE pfnNlReadValue = NULL; +static PFN_NLWRITEVALUE pfnNlWriteValue = NULL; +static PFN_NLGETTYPE pfnNlGetType = NULL; + +extern const long NlErrorCode; + +#if _WIN32 + +long NlLoadLibrary() { + long error = 0; + HMODULE h = LoadLibraryA(TheLibrary); + if (!h) { + error = HRESULT_FROM_WIN32(GetLastError()); + } + else { + /* load up the function pointer table */ + if (((pfnNlCreate = (PFN_NLCREATE)GetProcAddress(h, cNlCreate)) == NULL) || + ((pfnNlClose = (PFN_NLCLOSE)GetProcAddress(h, cNlClose)) == NULL) || + ((pfnNlReadValue = (PFN_NLREADVALUE)GetProcAddress(h, cNlReadValue)) == NULL) || + ((pfnNlWriteValue = (PFN_NLWRITEVALUE)GetProcAddress(h, cNlWriteValue)) == NULL) || + ((pfnNlGetType = (PFN_NLGETTYPE)GetProcAddress(h, cNlGetType)) == NULL)) { + error = HRESULT_FROM_WIN32(GetLastError()); + FreeLibrary(h); + h = NULL; + } + } + return error; +} + +#elif __APPLE__ + +long NlLoadLibrary() { + long error = 0; + void *libHandle = dlopen(TheLibrary, RTLD_LAZY | RTLD_LOCAL); + if (NULL == libHandle) { + error = -1; // whatever error it's an error dlopen() does not set errno + fprintf(stderr, "Error: Failed to open library \"%s\"! Error: %s!\n", TheLibrary, dlerror()); + } + else { + /* load up the function pointer table */ + if (((pfnNlCreate = (PFN_NLCREATE)dlsym(libHandle, cNlCreate)) == NULL) || + ((pfnNlClose = (PFN_NLCLOSE)dlsym(libHandle, cNlClose)) == NULL) || + ((pfnNlReadValue = (PFN_NLREADVALUE)dlsym(libHandle, cNlReadValue)) == NULL) || + ((pfnNlWriteValue = (PFN_NLWRITEVALUE)dlsym(libHandle, cNlWriteValue)) == NULL) || + ((pfnNlGetType = (PFN_NLGETTYPE)dlsym(libHandle, cNlGetType)) == NULL)) { + error = -2; // whatever error it is - it's an error dlsym() does not set errno + fprintf(stderr, "Error: Failed to fetch symbols from \"%s\"! Error: %s!\n", TheLibrary, + dlerror()); + + dlclose(libHandle); + libHandle = NULL; + } + } + return error; +} + +#else + +long NlLoadLibrary() { + return EOPNOTSUPP; +} + +#endif + +long __cdecl NlCreate(nlHandle_t *pnh, const char *appname, const accessor_t accessors[], + size_t accessor_count, const nlCreateOptions_t *options) { + if (pfnNlCreate) { + return pfnNlCreate(pnh, appname, accessors, accessor_count, options); + } + + return NlErrorCode; +} + +long __cdecl NlClose(nlHandle_t nh) { + if (pfnNlClose) { + return pfnNlClose(nh); + } + + return NlErrorCode; +} + +long __cdecl NlReadValue(nlHandle_t nh, property_t name, value_t *value) { + if (pfnNlReadValue) { + return pfnNlReadValue(nh, name, value); + } + + return NlErrorCode; +} + +long __cdecl NlWriteValue(nlHandle_t nh, property_t name, const value_t *value) { + if (pfnNlWriteValue) { + return pfnNlWriteValue(nh, name, value); + } + + return NlErrorCode; +} + +propertyType_t __cdecl NlGetType(property_t name) { + if (pfnNlGetType) { + return pfnNlGetType(name); + } + + return unknown_type; +}