ADDED: Spacemouse support for Linux

Uses libspnav to handle spacemouse data.  Overlays on existing
spacemouse framework to handle view activation

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16133
This commit is contained in:
Seth Hillbrand 2025-01-03 14:00:58 -08:00
parent b2fbb326b0
commit 0a5de5010f
34 changed files with 2132 additions and 9 deletions

View File

@ -0,0 +1,14 @@
if( UNIX AND NOT APPLE )
add_library(3d-viewer_spacenav STATIC
spnav_viewer_plugin.cpp
)
add_dependencies( 3d-viewer_spacenav pcbcommon )
target_include_directories(3d-viewer_spacenav PRIVATE
${CMAKE_SOURCE_DIR}/common
${CMAKE_SOURCE_DIR}/3d-viewer
)
target_link_libraries(3d-viewer_spacenav
PRIVATE
kicommon
)
endif()

View File

@ -0,0 +1,101 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "spnav_viewer_plugin.h"
#include <3d-viewer/3d_canvas/eda_3d_canvas.h>
#include <3d-viewer/3d_rendering/track_ball.h>
#include <pgm_base.h>
#include <settings/common_settings.h>
SPNAV_VIEWER_PLUGIN::SPNAV_VIEWER_PLUGIN( EDA_3D_CANVAS* aCanvas )
: m_timer( this ), m_canvas( aCanvas ), m_camera( nullptr ), m_focused( true )
{
m_camera = dynamic_cast<TRACK_BALL*>( aCanvas->GetCamera() );
m_driver = std::make_unique<LIBSPNAV_DRIVER>();
if( m_driver->Connect() )
{
m_driver->SetHandler( this );
Bind( wxEVT_TIMER, &SPNAV_VIEWER_PLUGIN::onPollTimer, this );
m_timer.Start( 10 );
}
}
SPNAV_VIEWER_PLUGIN::~SPNAV_VIEWER_PLUGIN()
{
m_timer.Stop();
if( m_driver )
m_driver->Disconnect();
}
void SPNAV_VIEWER_PLUGIN::SetFocus( bool aFocus )
{
m_focused = aFocus;
}
void SPNAV_VIEWER_PLUGIN::onPollTimer( wxTimerEvent& )
{
if( m_driver && m_focused )
m_driver->Poll();
}
void SPNAV_VIEWER_PLUGIN::OnPan( double x, double y, double z )
{
const COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
float scale = 0.0005f * ( cfg->m_SpaceMouse.pan_speed / 5.0f );
if( cfg->m_SpaceMouse.reverse_pan_x )
x = -x;
if( cfg->m_SpaceMouse.reverse_pan_y )
y = -y;
if( cfg->m_SpaceMouse.reverse_zoom )
z = -z;
if( m_camera )
{
m_camera->Pan( SFVEC3F( x * scale, -y * scale, z * scale ) );
m_canvas->Request_refresh();
}
}
void SPNAV_VIEWER_PLUGIN::OnRotate( double rx, double ry, double rz )
{
const COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
float scale = 0.001f * ( cfg->m_SpaceMouse.rotate_speed / 5.0f );
if( cfg->m_SpaceMouse.reverse_rotate )
scale = -scale;
if( m_camera )
{
m_camera->RotateX( ry * scale );
m_camera->RotateY( rx * scale );
m_camera->RotateZ( rz * scale );
m_canvas->Request_refresh();
}
}
void SPNAV_VIEWER_PLUGIN::OnButton( int button, bool pressed )
{
// Buttons are ignored for now
(void) button;
(void) pressed;
}

View File

@ -0,0 +1,57 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SPNAV_VIEWER_PLUGIN_H
#define SPNAV_VIEWER_PLUGIN_H
#include <memory>
#include <wx/timer.h>
#include "common/spacenav/spacenav_driver.h"
#include "common/spacenav/libspnav_driver.h"
class EDA_3D_CANVAS;
class TRACK_BALL;
class SPNAV_VIEWER_PLUGIN : public wxEvtHandler, public SPACEMOUSE_HANDLER
{
public:
explicit SPNAV_VIEWER_PLUGIN( EDA_3D_CANVAS* aCanvas );
~SPNAV_VIEWER_PLUGIN();
void SetFocus( bool aFocus = true );
void OnPan( double x, double y, double z ) override;
void OnRotate( double rx, double ry, double rz ) override;
void OnButton( int button, bool pressed ) override;
private:
void onPollTimer( wxTimerEvent& evt );
std::unique_ptr<SPACENAV_DRIVER> m_driver;
wxTimer m_timer;
EDA_3D_CANVAS* m_canvas;
TRACK_BALL* m_camera;
bool m_focused;
};
#endif // SPNAV_VIEWER_PLUGIN_H

View File

@ -61,7 +61,12 @@
#include <project_pcb.h>
#include <toolbars_3d.h>
#ifdef __linux__
#include <spacenav/libspnav_driver.h>
#include <3d_spacenav/spnav_viewer_plugin.h>
#else
#include <3d_navlib/nl_3d_viewer_plugin.h>
#endif
/**
* Flag to enable 3D viewer main frame window debug tracing.
@ -192,7 +197,11 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent
try
{
#ifdef __linux__
m_spaceMouse = std::make_unique<SPNAV_VIEWER_PLUGIN>( m_canvas );
#else
m_spaceMouse = std::make_unique<NL_3D_VIEWER_PLUGIN>( m_canvas );
#endif
}
catch( const std::system_error& e )
{

View File

@ -44,7 +44,11 @@
#define KICAD_DEFAULT_3D_DRAWFRAME_STYLE (wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS)
// Forward declarations
#ifdef __linux__
class SPNAV_VIEWER_PLUGIN;
#else
class NL_3D_VIEWER_PLUGIN;
#endif
class APPEARANCE_CONTROLS_3D;
@ -276,7 +280,11 @@ private:
bool m_disable_ray_tracing;
#ifdef __linux__
std::unique_ptr<SPNAV_VIEWER_PLUGIN> m_spaceMouse;
#else
std::unique_ptr<NL_3D_VIEWER_PLUGIN> m_spaceMouse;
#endif
/**
* Trace mask used to enable or disable the trace output of this class.

View File

@ -124,6 +124,13 @@ target_link_libraries( 3d-viewer
add_subdirectory( 3d_cache )
message( STATUS "Including 3Dconnexion SpaceMouse navigation support in 3d-viewer" )
add_subdirectory( 3d_navlib )
target_link_libraries( 3d-viewer PRIVATE 3d-viewer_navlib)
if( UNIX AND NOT APPLE )
message( STATUS "Including libspnav support in 3d-viewer" )
add_subdirectory( 3d_spacenav )
target_link_libraries( 3d-viewer PRIVATE 3d-viewer_spacenav )
else()
message( STATUS "Including 3Dconnexion SpaceMouse navigation support in 3d-viewer" )
add_subdirectory( 3d_navlib )
target_link_libraries( 3d-viewer PRIVATE 3d-viewer_navlib)
endif()

View File

@ -47,7 +47,11 @@
#include <eda_3d_viewer_settings.h>
#include <board_design_settings.h>
#ifndef __linux__
#include <3d_navlib/nl_footprint_properties_plugin.h>
#else
#include <3d_spacenav/spnav_viewer_plugin.h>
#endif
PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAME* aFrame,
FOOTPRINT* aFootprint,
@ -132,7 +136,11 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
try
{
#ifndef __linux__
m_spaceMouse = std::make_unique<NL_FOOTPRINT_PROPERTIES_PLUGIN>( m_previewPane );
#else
m_spaceMouse = std::make_unique<SPNAV_VIEWER_PLUGIN>( m_previewPane );
#endif
m_spaceMouse->SetFocus( true );
}
catch( const std::system_error& e )

View File

@ -62,7 +62,11 @@ class FILENAME_RESOLVER;
class BOARD;
class BOARD_ADAPTER;
class FOOTPRINT;
#ifndef __linux__
class NL_FOOTPRINT_PROPERTIES_PLUGIN;
#else
class SPNAV_VIEWER_PLUGIN;
#endif
#define PANEL_PREVIEW_3D_MODEL_ID wxID_HIGHEST + 1244
@ -226,7 +230,11 @@ private:
/// The 3d viewer Render initial settings (must be saved and restored)
EDA_3D_VIEWER_SETTINGS::RENDER_SETTINGS m_initialRender;
#ifndef __linux__
std::unique_ptr<NL_FOOTPRINT_PROPERTIES_PLUGIN> m_spaceMouse;
#else
std::unique_ptr<SPNAV_VIEWER_PLUGIN> m_spaceMouse;
#endif
};
#endif // PANEL_PREVIEW_3D_MODEL_H

View File

@ -780,6 +780,11 @@ find_package(ZSTD REQUIRED)
#
find_package( CURL REQUIRED )
if( UNIX AND NOT APPLE )
find_package( SPNAV REQUIRED )
include_directories( SYSTEM ${SPNAV_INCLUDE_DIR} )
endif()
#
# Find Cairo library, required
#

63
cmake/FindSPNAV.cmake Normal file
View File

@ -0,0 +1,63 @@
# BSD 3-Clause License
# Copyright (c) 2008, Willow Garage, Inc.
# Copyright (c) 2020, Nils Schulte
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Find the spnav library and header.
#
# Sets the usual variables expected for find_package scripts:
#
# SPNAV_INCLUDE_DIR - header location
# SPNAV_LIBRARIES - library to link against
# SPNAV_FOUND - true if pugixml was found.
if(UNIX)
find_path(SPNAV_INCLUDE_DIR spnav.h)
find_library(SPNAV_LIBRARY
NAMES
spnav libspnav
)
# Support the REQUIRED and QUIET arguments, and set spnav_FOUND if found.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SPNAV DEFAULT_MSG
SPNAV_LIBRARY
SPNAV_INCLUDE_DIR)
if(SPNAV_FOUND)
set(SPNAV_LIBRARIES ${SPNAV_LIBRARY})
endif()
mark_as_advanced(
SPNAV_LIBRARY
SPNAV_INCLUDE_DIR)
endif()

View File

@ -223,6 +223,12 @@ set( KICOMMON_SRCS
api/api_utils.cpp
)
if( UNIX AND NOT APPLE )
list( APPEND KICOMMON_SRCS
spacenav/libspnav_driver.cpp
)
endif()
if( KICAD_IPC_API )
set( KICOMMON_SRCS
${KICOMMON_SRCS}
@ -270,6 +276,7 @@ target_link_libraries( kicommon
${ZSTD_LIBRARY}
${wxWidgets_LIBRARIES}
${LIBGIT2_LIBRARIES}
${SPNAV_LIBRARIES}
# needed by kiid to allow linking for Boost for the UUID against bcrypt (msys2 only)
${EXTRA_LIBS}
@ -433,6 +440,8 @@ set( COMMON_DLG_SRCS
dialogs/panel_grid_settings_base.cpp
dialogs/panel_mouse_settings.cpp
dialogs/panel_mouse_settings_base.cpp
dialogs/panel_spacemouse.cpp
dialogs/panel_spacemouse_base.cpp
dialogs/panel_packages_and_updates.cpp
dialogs/panel_packages_and_updates_base.cpp
dialogs/panel_plugin_settings.cpp
@ -745,7 +754,14 @@ set( COMMON_SRCS
api/api_enums.cpp
)
if( KICAD_IPC_API )
# This needs to be in the common library until draw_panel_gal is moved to kicommon
if( UNIX AND NOT APPLE )
list( APPEND COMMON_SRCS
spacenav/spnav_2d_plugin.cpp
)
endif()
if( KICAD_IPC_API )
set( COMMON_SRCS
${COMMON_SRCS}
api/api_handler_common.cpp
@ -966,9 +982,12 @@ target_link_libraries( pcbcommon PUBLIC
nanoflann
)
message( STATUS "Including 3Dconnexion SpaceMouse navigation support in pcbcommon" )
add_subdirectory( ../pcbnew/navlib ./navlib)
target_link_libraries( pcbcommon PUBLIC pcbnew_navlib)
if( APPLE OR NOT UNIX )
# On Windows/MacOS, the SpaceMouse support is provided by the navlib subdirectory
message( STATUS "Including 3Dconnexion SpaceMouse navigation support in pcbcommon" )
add_subdirectory( ../pcbnew/navlib ./navlib)
target_link_libraries( pcbcommon PUBLIC pcbnew_navlib)
endif()
add_dependencies( pcbcommon delaunator )

View File

@ -0,0 +1,73 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 <http://www.gnu.org/licenses/>.
*/
#include <dialogs/panel_spacemouse.h>
#include <pgm_base.h>
#include <settings/common_settings.h>
PANEL_SPACEMOUSE::PANEL_SPACEMOUSE( wxWindow* aParent ) :
PANEL_SPACEMOUSE_BASE( aParent )
{
}
PANEL_SPACEMOUSE::~PANEL_SPACEMOUSE()
{
}
bool PANEL_SPACEMOUSE::TransferDataToWindow()
{
const COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
applySettingsToPanel( *cfg );
return true;
}
bool PANEL_SPACEMOUSE::TransferDataFromWindow()
{
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
cfg->m_SpaceMouse.rotate_speed = m_zoomSpeed->GetValue();
cfg->m_SpaceMouse.pan_speed = m_autoPanSpeed->GetValue();
cfg->m_SpaceMouse.reverse_rotate = m_checkEnablePanH->GetValue();
cfg->m_SpaceMouse.reverse_pan_y = m_reverseY->GetValue();
cfg->m_SpaceMouse.reverse_pan_x = m_reverseX->GetValue();
cfg->m_SpaceMouse.reverse_zoom = m_reverseZ->GetValue();
return true;
}
void PANEL_SPACEMOUSE::ResetPanel()
{
COMMON_SETTINGS defaultSettings;
defaultSettings.ResetToDefaults();
applySettingsToPanel( defaultSettings );
}
void PANEL_SPACEMOUSE::applySettingsToPanel( const COMMON_SETTINGS& aSettings )
{
m_zoomSpeed->SetValue( aSettings.m_SpaceMouse.rotate_speed );
m_autoPanSpeed->SetValue( aSettings.m_SpaceMouse.pan_speed );
m_checkEnablePanH->SetValue( aSettings.m_SpaceMouse.reverse_rotate );
m_reverseY->SetValue( aSettings.m_SpaceMouse.reverse_pan_y );
m_reverseX->SetValue( aSettings.m_SpaceMouse.reverse_pan_x );
m_reverseZ->SetValue( aSettings.m_SpaceMouse.reverse_zoom );
}

View File

@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "panel_spacemouse_base.h"
///////////////////////////////////////////////////////////////////////////
PANEL_SPACEMOUSE_BASE::PANEL_SPACEMOUSE_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : RESETTABLE_PANEL( parent, id, pos, size, style, name )
{
wxBoxSizer* bSizer10;
bSizer10 = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_panRotateLabel = new wxStaticText( this, wxID_ANY, _("Pan and Rotate"), wxDefaultPosition, wxDefaultSize, 0 );
m_panRotateLabel->Wrap( -1 );
bSizer1->Add( m_panRotateLabel, 0, wxTOP|wxRIGHT|wxLEFT, 13 );
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer1->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 2 );
wxBoxSizer* bSizer8;
bSizer8 = new wxBoxSizer( wxVERTICAL );
wxGridBagSizer* gbSizer1;
gbSizer1 = new wxGridBagSizer( 0, 0 );
gbSizer1->SetFlexibleDirection( wxBOTH );
gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Rotate speed:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1->Wrap( -1 );
gbSizer1->Add( m_staticText1, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT|wxRIGHT, 5 );
m_zoomSpeed = new wxSlider( this, wxID_ANY, 5, 1, 10, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
m_zoomSpeed->SetToolTip( _("How far to zoom in for each rotation of the mouse wheel") );
m_zoomSpeed->SetMinSize( wxSize( 120,-1 ) );
gbSizer1->Add( m_zoomSpeed, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT|wxRIGHT, 5 );
m_staticText22 = new wxStaticText( this, wxID_ANY, _("Pan speed:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText22->Wrap( -1 );
gbSizer1->Add( m_staticText22, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT|wxRIGHT, 5 );
m_autoPanSpeed = new wxSlider( this, wxID_ANY, 5, 1, 10, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
m_autoPanSpeed->SetToolTip( _("How fast to pan when moving an object off the edge of the screen") );
m_autoPanSpeed->SetMinSize( wxSize( 120,-1 ) );
gbSizer1->Add( m_autoPanSpeed, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT|wxRIGHT, 5 );
m_checkEnablePanH = new wxCheckBox( this, wxID_ANY, _("Reverse rotation direction"), wxDefaultPosition, wxDefaultSize, 0 );
m_checkEnablePanH->SetToolTip( _("Swap the direction of rotation") );
gbSizer1->Add( m_checkEnablePanH, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
m_reverseY = new wxCheckBox( this, wxID_ANY, _("Reverse vertical pan direction"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_reverseY, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxLEFT, 5 );
m_reverseX = new wxCheckBox( this, wxID_ANY, _("Reverse horizontal pan direction"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_reverseX, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxLEFT, 5 );
m_dummy1 = new wxSlider( this, wxID_ANY, 5, 1, 10, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
m_dummy1->Hide();
m_dummy1->SetMinSize( wxSize( 120,-1 ) );
gbSizer1->Add( m_dummy1, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxRIGHT, 5 );
m_reverseZ = new wxCheckBox( this, wxID_ANY, _("Reverse zoom direction"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_reverseZ, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxLEFT|wxRIGHT, 5 );
m_dummy2 = new wxSlider( this, wxID_ANY, 5, 1, 10, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
m_dummy2->Hide();
m_dummy2->SetMinSize( wxSize( 120,-1 ) );
gbSizer1->Add( m_dummy2, wxGBPosition( 3, 2 ), wxGBSpan( 1, 1 ), wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxRIGHT, 5 );
gbSizer1->AddGrowableCol( 0 );
gbSizer1->AddGrowableCol( 1 );
gbSizer1->AddGrowableCol( 2 );
bSizer8->Add( gbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bSizer1->Add( bSizer8, 0, wxEXPAND|wxRIGHT, 10 );
bSizer10->Add( bSizer1, 1, 0, 5 );
this->SetSizer( bSizer10 );
this->Layout();
bSizer10->Fit( this );
}
PANEL_SPACEMOUSE_BASE::~PANEL_SPACEMOUSE_BASE()
{
}

View File

@ -0,0 +1,904 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="18"/>
<object class="Project" expanded="true">
<property name="code_generation">C++</property>
<property name="cpp_class_decoration">; </property>
<property name="cpp_disconnect_events">1</property>
<property name="cpp_event_generation">connect</property>
<property name="cpp_help_provider">none</property>
<property name="cpp_namespace"></property>
<property name="cpp_precompiled_header"></property>
<property name="cpp_use_array_enum">0</property>
<property name="cpp_use_enum">1</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="file">panel_spacemouse_base</property>
<property name="first_id">10000</property>
<property name="internationalize">1</property>
<property name="lua_skip_events">1</property>
<property name="lua_ui_table">UI</property>
<property name="name">PANEL_SPACEMOUSE_BASE</property>
<property name="path">.</property>
<property name="php_disconnect_events">0</property>
<property name="php_disconnect_mode">source_name</property>
<property name="php_skip_events">1</property>
<property name="python_disconnect_events">0</property>
<property name="python_disconnect_mode">source_name</property>
<property name="python_image_path_wrapper_function_name"></property>
<property name="python_indent_with_spaces"></property>
<property name="python_skip_events">1</property>
<property name="relative_path">1</property>
<property name="use_microsoft_bom">0</property>
<property name="use_native_eol">0</property>
<object class="Panel" expanded="true">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">PANEL_SPACEMOUSE_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer10</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag"></property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer1</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">13</property>
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Pan and Rotate</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_panRotateLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">2</property>
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
<property name="proportion">0</property>
<object class="wxStaticLine" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticline1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLI_HORIZONTAL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer8</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxGridBagSizer" expanded="true">
<property name="empty_cell_size"></property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">0,1,2</property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">gbSizer1</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">none</property>
<property name="vgap">0</property>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT|wxRIGHT</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Rotate speed:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxSlider" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maxValue">10</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="minValue">1</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">120,-1</property>
<property name="moveable">1</property>
<property name="name">m_zoomSpeed</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxSL_HORIZONTAL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">How far to zoom in for each rotation of the mouse wheel</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">5</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT|wxRIGHT</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Pan speed:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText22</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxSlider" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maxValue">10</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="minValue">1</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">120,-1</property>
<property name="moveable">1</property>
<property name="name">m_autoPanSpeed</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxSL_HORIZONTAL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">How fast to pan when moving an object off the edge of the screen</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">5</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Reverse rotation direction</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_checkEnablePanH</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Swap the direction of rotation</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxLEFT</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Reverse vertical pan direction</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_reverseY</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxLEFT</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Reverse horizontal pan direction</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_reverseX</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxEXPAND|wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxRIGHT</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxSlider" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">1</property>
<property name="id">wxID_ANY</property>
<property name="maxValue">10</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="minValue">1</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">120,-1</property>
<property name="moveable">1</property>
<property name="name">m_dummy1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxSL_HORIZONTAL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">5</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxLEFT|wxRIGHT</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Reverse zoom direction</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_reverseZ</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxRIGHT</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxSlider" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">1</property>
<property name="id">wxID_ANY</property>
<property name="maxValue">10</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="minValue">1</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">120,-1</property>
<property name="moveable">1</property>
<property name="name">m_dummy2</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxSL_HORIZONTAL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">5</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,57 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include "widgets/resettable_panel.h"
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/statline.h>
#include <wx/slider.h>
#include <wx/checkbox.h>
#include <wx/gbsizer.h>
#include <wx/sizer.h>
#include <wx/panel.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class PANEL_SPACEMOUSE_BASE
///////////////////////////////////////////////////////////////////////////////
class PANEL_SPACEMOUSE_BASE : public RESETTABLE_PANEL
{
private:
protected:
wxStaticText* m_panRotateLabel;
wxStaticLine* m_staticline1;
wxStaticText* m_staticText1;
wxSlider* m_zoomSpeed;
wxStaticText* m_staticText22;
wxSlider* m_autoPanSpeed;
wxCheckBox* m_checkEnablePanH;
wxCheckBox* m_reverseY;
wxCheckBox* m_reverseX;
wxSlider* m_dummy1;
wxCheckBox* m_reverseZ;
wxSlider* m_dummy2;
public:
PANEL_SPACEMOUSE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~PANEL_SPACEMOUSE_BASE();
};

View File

@ -34,6 +34,7 @@
#include <dialogs/git/panel_git_repos.h>
#include <dialogs/panel_common_settings.h>
#include <dialogs/panel_mouse_settings.h>
#include <dialogs/panel_spacemouse.h>
#include <dialogs/panel_data_collection.h>
#include <dialogs/panel_plugin_settings.h>
#include <eda_dde.h>
@ -1229,6 +1230,12 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
return new PANEL_MOUSE_SETTINGS( aParent );
}, _( "Mouse and Touchpad" ) );
book->AddLazyPage(
[] ( wxWindow* aParent ) -> wxWindow*
{
return new PANEL_SPACEMOUSE( aParent );
}, _( "SpaceMouse" ) );
book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
book->AddLazyPage(

View File

@ -50,6 +50,7 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
m_Backup(),
m_Env(),
m_Input(),
m_SpaceMouse(),
m_Graphics(),
m_Session(),
m_System(),
@ -290,6 +291,24 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
&m_Input.drag_right, MOUSE_DRAG_ACTION::PAN, MOUSE_DRAG_ACTION::SELECT,
MOUSE_DRAG_ACTION::NONE ) );
m_params.emplace_back( new PARAM<int>( "spacemouse.rotate_speed",
&m_SpaceMouse.rotate_speed, 5, 1, 10 ) );
m_params.emplace_back( new PARAM<int>( "spacemouse.pan_speed",
&m_SpaceMouse.pan_speed, 5, 1, 10 ) );
m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_rotate",
&m_SpaceMouse.reverse_rotate, false ) );
m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_pan_x",
&m_SpaceMouse.reverse_pan_x, false ) );
m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_pan_y",
&m_SpaceMouse.reverse_pan_y, false ) );
m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_zoom",
&m_SpaceMouse.reverse_zoom, false ) );
m_params.emplace_back( new PARAM<int>( "graphics.canvas_type",
&m_Graphics.canvas_type, EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ) );

48
common/spacemouse.cpp Normal file
View File

@ -0,0 +1,48 @@
/*
*
* This file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 <http://www.gnu.org/licenses/>.
*/
#include "spacemouse.h"
#include <wx/event.h>
#include <class_draw_panel_gal.h>
LINUX_SPACEMOUSE::LINUX_SPACEMOUSE(EDA_DRAW_PANEL_GAL* parent)
: m_parent(parent)
{
m_parent->Bind( EVT_SPACEMOUSE_MOTION, &LINUX_SPACEMOUSE::OnSpaceMouseMotion );
m_parent->Bind( EVT_SPACEMOUSE_BUTTON, &LINUX_SPACEMOUSE::OnSpaceMouseButton );
}
LINUX_SPACEMOUSE::~LINUX_SPACEMOUSE()
{
m_parent->Unbind( EVT_SPACEMOUSE_MOTION, &LINUX_SPACEMOUSE::OnSpaceMouseMotion );
m_parent->Unbind( EVT_SPACEMOUSE_BUTTON, &LINUX_SPACEMOUSE::OnSpaceMouseButton );
}
void LINUX_SPACEMOUSE::OnSpaceMouseMotion()
{
// Handle SpaceMouse motion event
}
void LINUX_SPACEMOUSE::OnSpaceMouseButton()
{
// Handle SpaceMouse button event
}

View File

@ -0,0 +1,108 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "libspnav_driver.h"
#include <cstring>
#include <mutex>
// Static member definitions
std::mutex LIBSPNAV_DRIVER::s_mutex;
int LIBSPNAV_DRIVER::s_connection_count = 0;
bool LIBSPNAV_DRIVER::s_spnav_connected = false;
LIBSPNAV_DRIVER::LIBSPNAV_DRIVER()
{
}
LIBSPNAV_DRIVER::~LIBSPNAV_DRIVER()
{
Disconnect();
}
bool LIBSPNAV_DRIVER::Connect()
{
std::lock_guard<std::mutex> lock( s_mutex );
if( m_client_connected )
return true;
// If this is the first client, establish the connection to spacenavd
if( s_connection_count == 0 )
{
if( spnav_open() == -1 )
return false;
s_spnav_connected = true;
}
s_connection_count++;
m_client_connected = true;
return true;
}
void LIBSPNAV_DRIVER::Disconnect()
{
std::lock_guard<std::mutex> lock( s_mutex );
if( !m_client_connected )
return;
m_client_connected = false;
s_connection_count--;
// Close the connection when the last client disconnects
if( s_connection_count == 0 && s_spnav_connected )
{
spnav_close();
s_spnav_connected = false;
}
}
void LIBSPNAV_DRIVER::Poll()
{
// Only poll if this client is connected and has a handler
if( !m_client_connected || !m_handler )
return;
// Lock only for the duration of polling to prevent race conditions
// but allow other clients to poll independently
std::lock_guard<std::mutex> lock( s_mutex );
if( !s_spnav_connected )
return;
spnav_event sev;
while( spnav_poll_event( &sev ) > 0 )
{
if( sev.type == SPNAV_EVENT_MOTION )
{
m_handler->OnPan( sev.motion.x, sev.motion.y, sev.motion.z );
m_handler->OnRotate( sev.motion.rx, sev.motion.ry, sev.motion.rz );
}
else if( sev.type == SPNAV_EVENT_BUTTON )
{
m_handler->OnButton( sev.button.bnum, sev.button.press != 0 );
}
}
}

View File

@ -0,0 +1,55 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef KICAD_LIBSPNAV_DRIVER_H
#define KICAD_LIBSPNAV_DRIVER_H
#ifdef __linux__
#include <spnav.h>
#endif
#include <kicommon.h>
#include <mutex>
#include "spacenav_driver.h"
// Implementation of the SPACENAV_DRIVER using libspnav (spacenavd)
class KICOMMON_API LIBSPNAV_DRIVER : public SPACENAV_DRIVER
{
public:
LIBSPNAV_DRIVER();
~LIBSPNAV_DRIVER();
bool Connect() override;
void Disconnect() override;
void Poll() override;
private:
// Shared connection management
static std::mutex s_mutex;
static int s_connection_count;
static bool s_spnav_connected;
bool m_client_connected = false;
};
#endif // KICAD_LIBSPNAV_DRIVER_H

View File

@ -0,0 +1,60 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef KICAD_SPACENAV_DRIVER_H
#define KICAD_SPACENAV_DRIVER_H
class SPACEMOUSE_HANDLER
{
public:
virtual ~SPACEMOUSE_HANDLER() = default;
/** Handle translation (pan) events. Units are driver dependent. */
virtual void OnPan(double x, double y, double z) = 0;
/** Handle rotational events. Units are driver dependent. */
virtual void OnRotate(double rx, double ry, double rz) = 0;
/** Handle button press/release events. */
virtual void OnButton(int button, bool pressed) = 0;
};
class SPACENAV_DRIVER
{
public:
virtual ~SPACENAV_DRIVER() = default;
/** Connect to the device. Returns true on success. */
virtual bool Connect() = 0;
/** Disconnect from the device. */
virtual void Disconnect() = 0;
/** Poll for pending events and dispatch them to the handler. */
virtual void Poll() = 0;
void SetHandler( SPACEMOUSE_HANDLER* aHandler ) { m_handler = aHandler; }
protected:
SPACEMOUSE_HANDLER* m_handler = nullptr;
};
#endif // KICAD_SPACENAV_DRIVER_H

View File

@ -0,0 +1,140 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "spnav_2d_plugin.h"
#include <gal/graphics_abstraction_layer.h>
#include <class_draw_panel_gal.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
#include <wx/log.h>
#include <pgm_base.h>
#include <settings/common_settings.h>
SPNAV_2D_PLUGIN::SPNAV_2D_PLUGIN( EDA_DRAW_PANEL_GAL* aCanvas )
: m_timer( this ), m_canvas( aCanvas ), m_focused( true )
{
m_driver = std::make_unique<LIBSPNAV_DRIVER>();
m_view = aCanvas->GetView();
m_scale = 1.0;
if( m_driver->Connect() )
{
m_driver->SetHandler( this );
Bind( wxEVT_TIMER, &SPNAV_2D_PLUGIN::onPollTimer, this );
m_timer.Start( 10 );
}
}
SPNAV_2D_PLUGIN::~SPNAV_2D_PLUGIN()
{
m_timer.Stop();
if( m_driver )
m_driver->Disconnect();
}
void SPNAV_2D_PLUGIN::SetFocus( bool aFocus )
{
m_focused = aFocus;
}
void SPNAV_2D_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aCanvas )
{
m_canvas = aCanvas;
m_view = aCanvas->GetView();
}
void SPNAV_2D_PLUGIN::onPollTimer( wxTimerEvent& )
{
if( m_driver && m_focused )
m_driver->Poll();
}
void SPNAV_2D_PLUGIN::OnPan( double x, double y, double z )
{
const COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
double panFactor = cfg->m_SpaceMouse.pan_speed / 5.0;
wxLogTrace( "spacenav", "OnPan: x=%f, y=%f, z=%f", x, y, z );
if( !m_view )
return;
if( std::fabs( x ) > std::numeric_limits<double>::epsilon() ||
std::fabs( y ) > std::numeric_limits<double>::epsilon() ||
std::fabs( z ) > std::numeric_limits<double>::epsilon() )
{
double tx = x * panFactor;
double tz = z * panFactor;
if( cfg->m_SpaceMouse.reverse_pan_x )
tx = -tx;
if( cfg->m_SpaceMouse.reverse_pan_y )
tz = -tz;
VECTOR2D viewPos = m_view->GetCenter();
viewPos += m_view->ToWorld( VECTOR2D( tx, -tz ), false ) / 40.0;
m_view->SetCenter( viewPos );
double zoom = y * panFactor;
if( cfg->m_SpaceMouse.reverse_zoom )
zoom = -zoom;
double current_pixels = m_canvas->GetClientSize().GetWidth();
double current_scale = m_view->GetScale();
double desired_pixels = current_pixels + zoom / 10.0;
if( desired_pixels < 1 )
desired_pixels = 1;
double new_scale = current_scale * ( current_pixels / desired_pixels);
m_view->SetScale( new_scale, viewPos );
wxMouseEvent moveEvent( KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE );
VECTOR2D msp = m_canvas->GetViewControls()->GetMousePosition( false );
moveEvent.SetX( msp.x );
moveEvent.SetY( msp.y );
m_canvas->RequestRefresh();
wxPostEvent( m_canvas, moveEvent );
}
}
void SPNAV_2D_PLUGIN::OnRotate( double rx, double ry, double rz )
{
//Ignore the rotation
}
void SPNAV_2D_PLUGIN::OnButton( int button, bool pressed )
{
// Buttons are ignored for now
(void) button;
(void) pressed;
}

View File

@ -0,0 +1,71 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see CHANGELOG.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, you may find one here:
* http://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCBNEW_SPACENAV_2D_PLUGIN_H
#define PCBNEW_SPACENAV_2D_PLUGIN_H
#include <memory>
#include <wx/timer.h>
#include <kicommon.h>
#include <math/vector2d.h>
#include <spacenav/spacenav_driver.h>
#include <spacenav/libspnav_driver.h>
class EDA_DRAW_PANEL_GAL;
namespace KIGFX
{
class VIEW;
}
class KICOMMON_API SPNAV_2D_PLUGIN : public wxEvtHandler, public SPACEMOUSE_HANDLER
{
public:
explicit SPNAV_2D_PLUGIN( EDA_DRAW_PANEL_GAL* aCanvas );
~SPNAV_2D_PLUGIN();
void SetFocus( bool aFocus = true );
void SetCanvas( EDA_DRAW_PANEL_GAL* aCanvas );
void SetScale( double aScale )
{
m_scale = aScale;
}
void OnPan( double x, double y, double z ) override;
void OnRotate( double rx, double ry, double rz ) override;
void OnButton( int button, bool pressed ) override;
private:
void onPollTimer( wxTimerEvent& evt );
std::unique_ptr<SPACENAV_DRIVER> m_driver;
wxTimer m_timer;
EDA_DRAW_PANEL_GAL* m_canvas;
KIGFX::VIEW* m_view;
double m_scale;
bool m_focused;
};
#endif // PCBNEW_SPACENAV_2D_PLUGIN_H

View File

@ -60,8 +60,12 @@
#include <wx/log.h>
#include <wx/msgdlg.h>
#ifndef __linux__
#include <navlib/nl_schematic_plugin.h>
#include <wx/fdrepdlg.h>
#else
#include <spacenav/spnav_2d_plugin.h>
#endif
LIB_SYMBOL* SchGetLibSymbol( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable,
@ -364,7 +368,14 @@ void SCH_BASE_FRAME::ActivateGalCanvas()
try
{
if( !m_spaceMouse )
{
#ifndef __linux__
m_spaceMouse = std::make_unique<NL_SCHEMATIC_PLUGIN>();
#else
m_spaceMouse = std::make_unique<SPNAV_2D_PLUGIN>( GetCanvas() );
m_spaceMouse->SetScale( schIUScale.IU_PER_MILS / pcbIUScale.IU_PER_MILS );
#endif
}
m_spaceMouse->SetCanvas( GetCanvas() );
}

View File

@ -55,7 +55,13 @@ class LIB_ID;
class SYMBOL_LIB_TABLE;
class EESCHEMA_SETTINGS;
class SYMBOL_EDITOR_SETTINGS;
#ifndef __linux__
class NL_SCHEMATIC_PLUGIN;
#else
class SPNAV_2D_PLUGIN;
#endif
class PANEL_SCH_SELECTION_FILTER;
class DIALOG_SCH_FIND;
@ -327,7 +333,11 @@ private:
wxTimer m_watcherDebounceTimer;
bool m_inSymChangeTimerEvent;
#ifndef __linux__
std::unique_ptr<NL_SCHEMATIC_PLUGIN> m_spaceMouse;
#else
std::unique_ptr<SPNAV_2D_PLUGIN> m_spaceMouse;
#endif
};
#endif // SCH_BASE_FRAME_H_

View File

@ -59,7 +59,12 @@
#include "widgets/dcode_selection_box.h"
#include <dialog_draw_layers_settings.h>
#ifndef __linux__
#include <navlib/nl_gerbview_plugin.h>
#else
#include <spacenav/spnav_2d_plugin.h>
#endif
#include <wx/log.h>
GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
@ -1039,7 +1044,14 @@ void GERBVIEW_FRAME::ActivateGalCanvas()
try
{
if( !m_spaceMouse )
{
#ifndef __linux__
m_spaceMouse = std::make_unique<NL_GERBVIEW_PLUGIN>();
#else
m_spaceMouse = std::make_unique<SPNAV_2D_PLUGIN>( galCanvas );
m_spaceMouse->SetScale( gerbIUScale.IU_PER_MILS / pcbIUScale.IU_PER_MILS );
#endif
}
m_spaceMouse->SetCanvas( galCanvas );
}

View File

@ -45,7 +45,12 @@ class LSET;
class REPORTER;
class SELECTION;
class wxStaticText;
#ifndef __linux__
class NL_GERBVIEW_PLUGIN;
#else
class SPNAV_2D_PLUGIN;
#endif
/**
@ -517,7 +522,11 @@ private:
wxStaticText* m_dcodeText; // a message on the auxiliary toolbar,
// relative to the m_DCodeSelector
#ifndef __linux__
std::unique_ptr<NL_GERBVIEW_PLUGIN> m_spaceMouse;
#else
std::unique_ptr<SPNAV_2D_PLUGIN> m_spaceMouse;
#endif
};
#endif /* WX_GERBER_STRUCT_H */

View File

@ -0,0 +1,45 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KICAD_PANEL_SPACEMOUSE_H
#define KICAD_PANEL_SPACEMOUSE_H
#include <dialogs/panel_spacemouse_base.h>
class COMMON_SETTINGS;
class PANEL_SPACEMOUSE : public PANEL_SPACEMOUSE_BASE
{
public:
PANEL_SPACEMOUSE( wxWindow* aParent );
~PANEL_SPACEMOUSE();
void ResetPanel() override;
protected:
bool TransferDataFromWindow() override;
bool TransferDataToWindow() override;
private:
void applySettingsToPanel( const COMMON_SETTINGS& aSettings );
};
#endif

View File

@ -59,10 +59,15 @@ class PCB_VIEWERS_SETTINGS_BASE;
class PCBNEW_SETTINGS;
class FOOTPRINT_EDITOR_SETTINGS;
struct MAGNETIC_SETTINGS;
class NL_PCBNEW_PLUGIN;
class PROGRESS_REPORTER;
class PCB_LAYER_BOX_SELECTOR;
#ifndef __linux__
class NL_PCBNEW_PLUGIN;
#else
class SPNAV_2D_PLUGIN;
#endif
#ifdef wxHAS_INOTIFY
#define wxFileSystemWatcher wxInotifyFileSystemWatcher
#elif defined( wxHAS_KQUEUE ) && defined( wxHAVE_FSEVENTS_FILE_NOTIFICATIONS )
@ -430,7 +435,11 @@ protected:
PCB_ORIGIN_TRANSFORMS m_originTransforms;
private:
#ifndef __linux__
std::unique_ptr<NL_PCBNEW_PLUGIN> m_spaceMouse;
#else
std::unique_ptr<SPNAV_2D_PLUGIN> m_spaceMouse;
#endif
std::unique_ptr<wxFileSystemWatcher> m_watcher;
wxFileName m_watcherFileName;

View File

@ -106,6 +106,16 @@ public:
bool reverse_scroll_pan_h;
};
struct SPACEMOUSE
{
int rotate_speed;
int pan_speed;
bool reverse_rotate;
bool reverse_pan_x;
bool reverse_pan_y;
bool reverse_zoom;
};
struct GRAPHICS
{
int canvas_type; ///< EDA_DRAW_PANEL_GAL::GAL_TYPE_* value, see gal_options_panel.cpp
@ -220,6 +230,8 @@ public:
INPUT m_Input;
SPACEMOUSE m_SpaceMouse;
GRAPHICS m_Graphics;
SESSION m_Session;

43
include/spacemouse.h Normal file
View File

@ -0,0 +1,43 @@
/*
*
* This file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KICAD_SPACEMOUSE_H
#define KICAD_SPACEMOUSE_H
#include <wx/event.h>
// Define new events for SpaceMouse motion and button
wxDECLARE_EVENT(EVT_SPACEMOUSE_MOTION, wxCommandEvent);
wxDECLARE_EVENT(EVT_SPACEMOUSE_BUTTON, wxCommandEvent);
class EDA_DRAW_PANEL_GAL;
class LINUX_SPACEMOUSE
{
public:
LINUX_SPACEMOUSE(EDA_DRAW_PANEL_GAL* parent);
~LINUX_SPACEMOUSE();
private:
EDA_DRAW_PANEL_GAL* m_parent;
void OnSpaceMouseMotion();
void OnSpaceMouseButton();
};
#endif // KICAD_SPACEMOUSE_H

View File

@ -65,7 +65,11 @@
#include <wx/msgdlg.h>
#include <wx/log.h>
#ifndef __linux__
#include <navlib/nl_pl_editor_plugin.h>
#else
#include <spacenav/spnav_2d_plugin.h>
#endif
BEGIN_EVENT_TABLE( PL_EDITOR_FRAME, EDA_DRAW_FRAME )
@ -235,7 +239,15 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
try
{
if( !m_spaceMouse )
{
#ifndef __linux__
m_spaceMouse = std::make_unique<NL_PL_EDITOR_PLUGIN>();
#else
m_spaceMouse = std::make_unique<SPNAV_2D_PLUGIN>( GetCanvas() );
m_spaceMouse->SetScale( drawSheetIUScale.IU_PER_MILS / pcbIUScale.IU_PER_MILS );
#endif
}
m_spaceMouse->SetCanvas( GetCanvas() );
}
catch( const std::system_error& e )

View File

@ -38,8 +38,12 @@ class PL_DRAW_PANEL_GAL;
class PROPERTIES_FRAME;
class DS_DATA_ITEM;
class wxChoice;
class NL_PL_EDITOR_PLUGIN;
#ifndef __linux__
class NL_PL_EDITOR_PLUGIN;
#else
class SPNAV_2D_PLUGIN;
#endif
/**
* The main window used in the drawing sheet editor.
@ -270,7 +274,11 @@ private:
// only on page 1, not on page 1
VECTOR2I m_grid_origin;
#ifndef __linux__
std::unique_ptr<NL_PL_EDITOR_PLUGIN> m_spaceMouse;
#else
std::unique_ptr<SPNAV_2D_PLUGIN> m_spaceMouse;
#endif
wxString m_originChoiceList[5] =
{

View File

@ -67,7 +67,11 @@
#include <tool/grid_menu.h>
#include <ratsnest/ratsnest_view_item.h>
#ifdef __linux__
#include <spacenav/spnav_2d_plugin.h>
#else
#include <navlib/nl_pcbnew_plugin.h>
#endif
using KIGFX::RENDER_SETTINGS;
using KIGFX::PCB_RENDER_SETTINGS;
@ -1033,7 +1037,12 @@ void PCB_BASE_FRAME::ActivateGalCanvas()
{
if( !m_spaceMouse )
{
#ifndef __linux__
m_spaceMouse = std::make_unique<NL_PCBNEW_PLUGIN>( GetCanvas() );
#else
m_spaceMouse = std::make_unique<SPNAV_2D_PLUGIN>( GetCanvas() );
m_spaceMouse->SetScale( 0.01 );
#endif
}
}
catch( const std::system_error& e )