diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.cpp b/3d-viewer/3d_canvas/eda_3d_canvas.cpp index 2e2f4e0006..60f2eb5a13 100644 --- a/3d-viewer/3d_canvas/eda_3d_canvas.cpp +++ b/3d-viewer/3d_canvas/eda_3d_canvas.cpp @@ -532,7 +532,9 @@ void EDA_3D_CANVAS::DoRePaint() render_pivot( curtime_delta_s, scale ); } - if( m_render3dmousePivot && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + // This will only be enabled by the 3d mouse plugin, so we can leave + // it as a simple if statement + if( m_render3dmousePivot ) { const float scale = glm::min( m_camera.GetZoom(), 1.0f ); render3dmousePivot( scale ); diff --git a/3d-viewer/3d_navlib/nl_3d_viewer_plugin.cpp b/3d-viewer/3d_navlib/nl_3d_viewer_plugin.cpp index aa0228b03b..1fa3e309eb 100644 --- a/3d-viewer/3d_navlib/nl_3d_viewer_plugin.cpp +++ b/3d-viewer/3d_navlib/nl_3d_viewer_plugin.cpp @@ -21,14 +21,17 @@ #include "nl_3d_viewer_plugin.h" #include "nl_3d_viewer_plugin_impl.h" #include +#include NL_3D_VIEWER_PLUGIN::NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport ) + : m_impl( nullptr ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver + && KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() ) + { m_impl = new NL_3D_VIEWER_PLUGIN_IMPL( aViewport ); - else - m_impl = nullptr; + } } @@ -40,6 +43,6 @@ NL_3D_VIEWER_PLUGIN::~NL_3D_VIEWER_PLUGIN() void NL_3D_VIEWER_PLUGIN::SetFocus( bool focus ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_impl ) m_impl->SetFocus( focus ); } diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp index e46d1c0613..d01617f63b 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp +++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp @@ -165,17 +165,13 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent m_canvas->SetInfoBar( m_infoBar ); m_canvas->SetStatusBar( status_bar ); - - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + try { - try - { - m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas ); - } - catch( const std::system_error& e ) - { - wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); - } + m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas ); + } + catch( const std::system_error& e ) + { + wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); } // Fixes bug in Windows (XP and possibly others) where the canvas requires the focus @@ -336,11 +332,8 @@ void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent ) { KIWAY_PLAYER::handleIconizeEvent( aEvent ); - if( m_spaceMouse != nullptr && aEvent.IsIconized() - && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) - { + if( m_spaceMouse && aEvent.IsIconized() ) m_spaceMouse->SetFocus( false ); - } } @@ -656,7 +649,7 @@ void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent ) m_canvas->SetFocus(); } - if( m_spaceMouse != nullptr && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_spaceMouse ) m_spaceMouse->SetFocus( aEvent.GetActive() ); aEvent.Skip(); // required under wxMAC diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index fcf4e7d63b..bcbf19320a 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -337,12 +337,7 @@ ADVANCED_CFG::ADVANCED_CFG() m_UseClipper2 = true; -#ifdef _WIN32 - // spacemouse is largely stable on Windows - m_Use3DConnexionDriver = true; -#else - m_Use3DConnexionDriver = false; -#endif + m_Use3DConnexionDriver = true; m_IncrementalConnectivity = false; diff --git a/eeschema/navlib/nl_schematic_plugin.cpp b/eeschema/navlib/nl_schematic_plugin.cpp index 9057b1062d..bfa814e9b8 100644 --- a/eeschema/navlib/nl_schematic_plugin.cpp +++ b/eeschema/navlib/nl_schematic_plugin.cpp @@ -20,16 +20,18 @@ #include "nl_schematic_plugin.h" #include +#include #include "nl_schematic_plugin_impl.h" -NL_SCHEMATIC_PLUGIN::NL_SCHEMATIC_PLUGIN() +NL_SCHEMATIC_PLUGIN::NL_SCHEMATIC_PLUGIN() : m_impl( nullptr ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver + && KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() ) + { m_impl = new NL_SCHEMATIC_PLUGIN_IMPL(); - else - m_impl = nullptr; + } } @@ -41,13 +43,13 @@ NL_SCHEMATIC_PLUGIN::~NL_SCHEMATIC_PLUGIN() void NL_SCHEMATIC_PLUGIN::SetFocus( bool focus ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_impl ) m_impl->SetFocus( focus ); } void NL_SCHEMATIC_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_impl ) m_impl->SetCanvas( aViewport ); } diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp index e2c0ff145a..f789470bb0 100644 --- a/eeschema/sch_base_frame.cpp +++ b/eeschema/sch_base_frame.cpp @@ -345,19 +345,16 @@ void SCH_BASE_FRAME::ActivateGalCanvas() { EDA_DRAW_FRAME::ActivateGalCanvas(); - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + try { - try - { - if( !m_spaceMouse ) - m_spaceMouse = new NL_SCHEMATIC_PLUGIN(); + if( !m_spaceMouse ) + m_spaceMouse = new NL_SCHEMATIC_PLUGIN(); - m_spaceMouse->SetCanvas( GetCanvas() ); - } - catch( const std::system_error& e ) - { - wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); - } + m_spaceMouse->SetCanvas( GetCanvas() ); + } + catch( const std::system_error& e ) + { + wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); } } @@ -537,7 +534,7 @@ void SCH_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent ) { EDA_DRAW_FRAME::handleActivateEvent( aEvent ); - if( m_spaceMouse && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_spaceMouse ) m_spaceMouse->SetFocus( aEvent.GetActive() ); } @@ -546,7 +543,7 @@ void SCH_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent ) { EDA_DRAW_FRAME::handleIconizeEvent( aEvent ); - if( m_spaceMouse && aEvent.IsIconized() && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_spaceMouse ) m_spaceMouse->SetFocus( false ); } diff --git a/libs/core/CMakeLists.txt b/libs/core/CMakeLists.txt index 6d93f6519b..3c49400e51 100644 --- a/libs/core/CMakeLists.txt +++ b/libs/core/CMakeLists.txt @@ -6,6 +6,7 @@ endif() add_library( core STATIC + version_compare.cpp wx_stl_compat.cpp ) diff --git a/libs/core/include/core/version_compare.h b/libs/core/include/core/version_compare.h new file mode 100644 index 0000000000..0fa6644707 --- /dev/null +++ b/libs/core/include/core/version_compare.h @@ -0,0 +1,36 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. +* +* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation, either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#include +#include + +/** + * @brief Parse a version string into a vector of integers + * @param versionString The version string to parse + * @return A vector of integers representing the version +*/ +const std::vector parseVersionString( const std::string& versionString ); + +/** + * @brief Compare two version strings of the form "major.minor.patch.build" + * @param aVersionStr1 The first version string + * @param aVersionStr2 The second version string + * @return true if aVersionStr1 <= aVersionStr2, false otherwise +*/ +bool compareVersionStrings( const std::string& aVersionStr1, const std::string& aVersionStr2 ); \ No newline at end of file diff --git a/libs/core/version_compare.cpp b/libs/core/version_compare.cpp new file mode 100644 index 0000000000..0b79a3058e --- /dev/null +++ b/libs/core/version_compare.cpp @@ -0,0 +1,67 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. +* +* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation, either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#include +#include + +const std::vector parseVersionString( const std::string& versionString ) +{ + std::vector versionComponents; + auto it = versionString.begin(); + auto end = versionString.end(); + + while( it != end ) + { + versionComponents.emplace_back( 0 ); + + // On error, the last element will be 0 + auto result = std::from_chars( &( *it ), &( *end ), versionComponents.back() ); + + it += std::distance( &( *it ), result.ptr ); // Update the iterator + if( it != end && *it == '.' ) + { + ++it; // Skip the dot separator + } + } + + return versionComponents; +} + + +bool compareVersionStrings( const std::string& aVersionStr1, const std::string& aVersionStr2 ) +{ + std::vector ver1 = parseVersionString( aVersionStr1 ); + std::vector ver2 = parseVersionString( aVersionStr2 ); + std::size_t len = std::min( ver1.size(), ver2.size() ); + + // Compare each component + for( size_t ii = 0; ii < len; ++ii ) + { + if( ver1[ii] < ver2[ii] ) + { + return true; // aVersionStr1 < aVersionStr2 + } + else if( ver1[ii] > ver2[ii] ) + { + return false; // aVersionStr1 > aVersionStr2 + } + } + + return ver1.size() >= ver2.size(); +} \ No newline at end of file diff --git a/libs/kiplatform/CMakeLists.txt b/libs/kiplatform/CMakeLists.txt index c86fa18b05..77bde73837 100644 --- a/libs/kiplatform/CMakeLists.txt +++ b/libs/kiplatform/CMakeLists.txt @@ -10,6 +10,7 @@ set( PLATFORM_COMPILE_DEFS "" ) if( APPLE ) set( PLATFORM_SRCS osx/app.mm + osx/drivers.mm osx/environment.mm osx/io.mm osx/policy.mm @@ -25,6 +26,7 @@ if( APPLE ) elseif( WIN32 ) set( PLATFORM_SRCS msw/app.cpp + msw/drivers.cpp msw/environment.cpp msw/io.cpp msw/policy.cpp @@ -40,6 +42,7 @@ elseif( WIN32 ) elseif( UNIX ) set( PLATFORM_SRCS gtk/app.cpp + gtk/drivers.cpp gtk/environment.cpp gtk/io.cpp gtk/policy.cpp diff --git a/libs/kiplatform/gtk/drivers.cpp b/libs/kiplatform/gtk/drivers.cpp new file mode 100644 index 0000000000..e8cda800e1 --- /dev/null +++ b/libs/kiplatform/gtk/drivers.cpp @@ -0,0 +1,25 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. +* +* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation, either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ +#include + +bool KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() +{ + // The 3DConnexion driver doesn't work for Linux + return false; +} \ No newline at end of file diff --git a/libs/kiplatform/include/kiplatform/drivers.h b/libs/kiplatform/include/kiplatform/drivers.h new file mode 100644 index 0000000000..33f702ab01 --- /dev/null +++ b/libs/kiplatform/include/kiplatform/drivers.h @@ -0,0 +1,40 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. +* +* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation, either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#ifndef KIPLATFORM_DRIVERS_H_ +#define KIPLATFORM_DRIVERS_H_ + +#include +#include +#include + +namespace KIPLATFORM +{ +namespace DRIVERS +{ + /** + * @brief Get the driver version for a given driver name + * @return true if the driver version is valid, false otherwise + */ + bool Valid3DConnexionDriverVersion(); + +} // namespace DRIVERS +} // namespace KIPLATFORM + +#endif // KIPLATFORM_DRIVERS_H_ \ No newline at end of file diff --git a/libs/kiplatform/msw/drivers.cpp b/libs/kiplatform/msw/drivers.cpp new file mode 100644 index 0000000000..2d271361b7 --- /dev/null +++ b/libs/kiplatform/msw/drivers.cpp @@ -0,0 +1,52 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. +* +* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation, either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#include +#include + +#include +#include + +#define MIN_WIN_VERSION "10.7.2" + +bool KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() +{ + HKEY hKey; + std::string version; + + // Open the registry key for 3dConnexion + if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "Software\\3Dconnexion\\3DxWare Version", + 0, KEY_READ, &hKey ) == ERROR_SUCCESS ) + { + char buffer[256]; + DWORD bufferSize = sizeof( buffer ); + + // Query the version value + if( RegQueryValueEx( hKey, nullptr, nullptr, nullptr, ( LPBYTE ) buffer, &bufferSize ) + == ERROR_SUCCESS ) + { + version = buffer; + } + + RegCloseKey( hKey ); + } + + return !version.empty() && compareVersionStrings( MIN_WIN_VERSION, version ); +} \ No newline at end of file diff --git a/libs/kiplatform/osx/drivers.mm b/libs/kiplatform/osx/drivers.mm new file mode 100644 index 0000000000..f55972ee44 --- /dev/null +++ b/libs/kiplatform/osx/drivers.mm @@ -0,0 +1,42 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. +* +* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation, either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#include +#include + +#import + +#define MIN_MAC_VERSION "10.8.0" + +bool KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() +{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSLocalDomainMask, YES); + NSString *libraryDirectory = searchPaths.firstObject; + NSString *frameworkPath = [libraryDirectory stringByAppendingPathComponent:@"Frameworks/3DconnexionNavlib.framework"]; + + NSBundle *frameworkBundle = [NSBundle bundleWithPath:frameworkPath]; + NSDictionary *infoDictionary = [frameworkBundle infoDictionary]; + NSString *version = infoDictionary[@"CFBundleShortVersionString"]; + + if (!version) + return false; + + return compareVersions(version.UTF8String, MIN_MAC_VERSION ) >= 0; +} \ No newline at end of file diff --git a/pcbnew/navlib/nl_pcbnew_plugin.cpp b/pcbnew/navlib/nl_pcbnew_plugin.cpp index 4dc5ceb209..d7b7e0ff53 100644 --- a/pcbnew/navlib/nl_pcbnew_plugin.cpp +++ b/pcbnew/navlib/nl_pcbnew_plugin.cpp @@ -21,14 +21,15 @@ #include "nl_pcbnew_plugin.h" #include "nl_pcbnew_plugin_impl.h" #include +#include - -NL_PCBNEW_PLUGIN::NL_PCBNEW_PLUGIN( PCB_DRAW_PANEL_GAL* aViewport ) +NL_PCBNEW_PLUGIN::NL_PCBNEW_PLUGIN( PCB_DRAW_PANEL_GAL* aViewport ) : m_impl( nullptr ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver + && KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() ) + { m_impl = new NL_PCBNEW_PLUGIN_IMPL( aViewport ); - else - m_impl = nullptr; + } } @@ -40,6 +41,6 @@ NL_PCBNEW_PLUGIN::~NL_PCBNEW_PLUGIN() void NL_PCBNEW_PLUGIN::SetFocus( bool focus ) { - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_impl ) m_impl->SetFocus( focus ); } diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp index 82645f975a..fe68e29f20 100644 --- a/pcbnew/pcb_base_frame.cpp +++ b/pcbnew/pcb_base_frame.cpp @@ -120,7 +120,7 @@ void PCB_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent ) { EDA_DRAW_FRAME::handleActivateEvent( aEvent ); - if( m_spaceMouse != nullptr && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_spaceMouse ) m_spaceMouse->SetFocus( aEvent.GetActive() ); } @@ -129,8 +129,7 @@ void PCB_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent ) { EDA_DRAW_FRAME::handleIconizeEvent( aEvent ); - if( m_spaceMouse != nullptr && aEvent.IsIconized() - && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) + if( m_spaceMouse != nullptr && aEvent.IsIconized() ) m_spaceMouse->SetFocus( false ); } @@ -1082,21 +1081,18 @@ void PCB_BASE_FRAME::ActivateGalCanvas() canvas->SetEventDispatcher( m_toolDispatcher ); canvas->StartDrawing(); - if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) - { - try + try + { + if( m_spaceMouse == nullptr ) { - if( m_spaceMouse == nullptr ) - { - m_spaceMouse = new NL_PCBNEW_PLUGIN( GetCanvas() ); - } - } - catch( const std::system_error& e ) - { - wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); + m_spaceMouse = new NL_PCBNEW_PLUGIN( GetCanvas() ); } } + catch( const std::system_error& e ) + { + wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); + } }