Browse Source
ADDED: 3D Mouse support in Gerber Viewer and Drawing Sheet Editor
ADDED: 3D Mouse support in Gerber Viewer and Drawing Sheet Editor
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13306jobs
committed by
Seth Hillbrand
16 changed files with 1889 additions and 18 deletions
-
7gerbview/CMakeLists.txt
-
50gerbview/gerbview_frame.cpp
-
8gerbview/gerbview_frame.h
-
25gerbview/navlib/CMakeLists.txt
-
52gerbview/navlib/nl_gerbview_plugin.cpp
-
69gerbview/navlib/nl_gerbview_plugin.h
-
598gerbview/navlib/nl_gerbview_plugin_impl.cpp
-
147gerbview/navlib/nl_gerbview_plugin_impl.h
-
7pagelayout_editor/CMakeLists.txt
-
25pagelayout_editor/navlib/CMakeLists.txt
-
52pagelayout_editor/navlib/nl_pl_editor_plugin.cpp
-
69pagelayout_editor/navlib/nl_pl_editor_plugin.h
-
598pagelayout_editor/navlib/nl_pl_editor_plugin_impl.cpp
-
147pagelayout_editor/navlib/nl_pl_editor_plugin_impl.h
-
44pagelayout_editor/pl_editor_frame.cpp
-
9pagelayout_editor/pl_editor_frame.h
@ -0,0 +1,25 @@ |
|||||
|
|
||||
|
add_library(gerbview_navlib STATIC |
||||
|
"nl_gerbview_plugin.cpp" |
||||
|
"nl_gerbview_plugin_impl.cpp" |
||||
|
) |
||||
|
|
||||
|
# gerbview_navlib depends on make_lexer outputs in common |
||||
|
add_dependencies( gerbview_navlib common ) |
||||
|
|
||||
|
# Find the 3DxWare SDK component 3DxWare::NlClient |
||||
|
# find_package(TDxWare_SDK 4.0 REQUIRED COMPONENTS 3DxWare::Navlib) |
||||
|
target_compile_definitions(gerbview_navlib PRIVATE |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_DEFINITIONS> |
||||
|
) |
||||
|
target_compile_options(gerbview_navlib PRIVATE |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_OPTIONS> |
||||
|
) |
||||
|
target_include_directories(gerbview_navlib PRIVATE |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_INCLUDE_DIRECTORIES> |
||||
|
$<TARGET_PROPERTY:gerbview_kiface_objects,INCLUDE_DIRECTORIES> |
||||
|
) |
||||
|
target_link_libraries(gerbview_navlib |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_LINK_LIBRARIES> |
||||
|
3DxWare::Navlib |
||||
|
) |
@ -0,0 +1,52 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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 "nl_gerbview_plugin.h"
|
||||
|
#include "nl_gerbview_plugin_impl.h"
|
||||
|
|
||||
|
#include <advanced_config.h>
|
||||
|
#include <kiplatform/drivers.h>
|
||||
|
|
||||
|
|
||||
|
NL_GERBVIEW_PLUGIN::NL_GERBVIEW_PLUGIN() |
||||
|
{ |
||||
|
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver |
||||
|
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() ) |
||||
|
{ |
||||
|
m_impl = std::make_unique<NL_GERBVIEW_PLUGIN_IMPL>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
NL_GERBVIEW_PLUGIN::~NL_GERBVIEW_PLUGIN() = default; |
||||
|
|
||||
|
|
||||
|
void NL_GERBVIEW_PLUGIN::SetFocus( bool focus ) |
||||
|
{ |
||||
|
if( m_impl ) |
||||
|
m_impl->SetFocus( focus ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_GERBVIEW_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ) |
||||
|
{ |
||||
|
if( m_impl ) |
||||
|
m_impl->SetCanvas( aViewport ); |
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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/>. |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @file nl_gerbview_plugin.h |
||||
|
* @brief Declaration of the NL_GERBVIEW_PLUGIN class |
||||
|
*/ |
||||
|
|
||||
|
#ifndef NL_GERBVIEW_PLUGIN_H_ |
||||
|
#define NL_GERBVIEW_PLUGIN_H_ |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
// Forward declarations. |
||||
|
class EDA_DRAW_PANEL_GAL; |
||||
|
class NL_GERBVIEW_PLUGIN_IMPL; |
||||
|
|
||||
|
/** |
||||
|
* The class that implements the public interface to the SpaceMouse plug-in. |
||||
|
*/ |
||||
|
class NL_GERBVIEW_PLUGIN |
||||
|
{ |
||||
|
public: |
||||
|
/** |
||||
|
* Initializes a new instance of the NL_GERBVIEW_PLUGIN. |
||||
|
*/ |
||||
|
NL_GERBVIEW_PLUGIN(); |
||||
|
|
||||
|
virtual ~NL_GERBVIEW_PLUGIN(); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Sets the viewport controlled by the SpaceMouse. |
||||
|
* |
||||
|
* @param aViewport is the viewport to be navigated. |
||||
|
*/ |
||||
|
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Set the connection to the 3Dconnexion driver to the focus state so that |
||||
|
* 3DMouse data is routed to this connexion. |
||||
|
* |
||||
|
* @param aFocus is true to set the connexion active. |
||||
|
*/ |
||||
|
void SetFocus( bool aFocus ); |
||||
|
|
||||
|
private: |
||||
|
std::unique_ptr<NL_GERBVIEW_PLUGIN_IMPL> m_impl; |
||||
|
}; |
||||
|
|
||||
|
#endif // NL_GERBVIEW_PLUGIN_H_ |
@ -0,0 +1,598 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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 "nl_gerbview_plugin_impl.h"
|
||||
|
|
||||
|
// KiCAD includes
|
||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||
|
#include <gerbview_frame.h>
|
||||
|
#include <bitmaps.h>
|
||||
|
#include <class_draw_panel_gal.h>
|
||||
|
#include <view/view.h>
|
||||
|
#include <view/wx_view_controls.h>
|
||||
|
#include <tool/action_manager.h>
|
||||
|
#include <tool/tool_action.h>
|
||||
|
#include <tool/tool_manager.h>
|
||||
|
|
||||
|
// stdlib
|
||||
|
#include <list>
|
||||
|
#include <map>
|
||||
|
#include <memory>
|
||||
|
#include <utility>
|
||||
|
#include <vector>
|
||||
|
#include <cfloat>
|
||||
|
|
||||
|
#include <wx/log.h>
|
||||
|
#include <wx/mstream.h>
|
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Flag to enable the NL_GERBVIEW_PLUGIN debug tracing. |
||||
|
* |
||||
|
* Use "KI_TRACE_NL_GERBVIEW_PLUGIN" to enable. |
||||
|
* |
||||
|
* @ingroup trace_env_vars |
||||
|
*/ |
||||
|
const wxChar* NL_GERBVIEW_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_GERBVIEW_PLUGIN" ); |
||||
|
|
||||
|
|
||||
|
NL_GERBVIEW_PLUGIN_IMPL::NL_GERBVIEW_PLUGIN_IMPL() : CNavigation3D( false, false ) |
||||
|
{ |
||||
|
PutProfileHint( "KiCAD Gerbview" ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
NL_GERBVIEW_PLUGIN_IMPL::~NL_GERBVIEW_PLUGIN_IMPL() |
||||
|
{ |
||||
|
std::error_code m_errCode; |
||||
|
EnableNavigation( false, m_errCode ); |
||||
|
if( m_errCode.value() != 0 ) |
||||
|
{ |
||||
|
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), |
||||
|
wxT( "Error occured when calling EnableNavigation. Error code: %d" ), |
||||
|
m_errCode.value() ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_GERBVIEW_PLUGIN_IMPL::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ) |
||||
|
{ |
||||
|
m_viewport2D = aViewport; |
||||
|
|
||||
|
if( m_viewport2D == nullptr ) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
m_view = m_viewport2D->GetView(); |
||||
|
|
||||
|
if( m_view == nullptr ) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
m_viewportWidth = m_view->GetBoundary().GetWidth(); |
||||
|
|
||||
|
if( !IsEnabled() ) |
||||
|
{ |
||||
|
// Use the default settings for the connexion to the 3DMouse navigation
|
||||
|
// They are use a single-threaded threading model and row vectors.
|
||||
|
EnableNavigation( true ); |
||||
|
|
||||
|
// Use the SpaceMouse internal timing source for the frame rate.
|
||||
|
PutFrameTimingSource( TimingSource::SpaceMouse ); |
||||
|
|
||||
|
exportCommandsAndImages(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_GERBVIEW_PLUGIN_IMPL::SetFocus( bool aFocus ) |
||||
|
{ |
||||
|
wxLogTrace( m_logTrace, wxT( "NL_GERBVIEW_PLUGIN_IMPL::SetFocus %d" ), aFocus ); |
||||
|
NAV_3D::Write( navlib::focus_k, aFocus ); |
||||
|
} |
||||
|
|
||||
|
// temporary store for the command categories
|
||||
|
using CATEGORY_STORE = std::map<std::string, TDx::CCommandTreeNode*, std::less<>>; |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Add a category to the store. |
||||
|
* |
||||
|
* The function adds category paths of the format "A.B" where B is a sub-category of A. |
||||
|
* |
||||
|
* @param aCategoryPath is the std::string representation of the category. |
||||
|
* @param aCategoryStore is the CATEGORY_STORE instance to add to. |
||||
|
*/ |
||||
|
static void add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore ) |
||||
|
{ |
||||
|
using TDx::SpaceMouse::CCategory; |
||||
|
|
||||
|
auto parent_iter = aCategoryStore.begin(); |
||||
|
std::string::size_type pos = aCategoryPath.find_last_of( '.' ); |
||||
|
|
||||
|
if( pos != std::string::npos ) |
||||
|
{ |
||||
|
std::string parentPath = aCategoryPath.substr( 0, pos ); |
||||
|
|
||||
|
if( !aCategoryStore.contains( parentPath ) ) |
||||
|
{ |
||||
|
add_category( parentPath, aCategoryStore ); |
||||
|
parent_iter = aCategoryStore.find( parentPath ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
std::string name = aCategoryPath.substr( pos + 1 ); |
||||
|
auto categoryNode = std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() ); |
||||
|
|
||||
|
aCategoryStore.try_emplace( aCategoryStore.end(), aCategoryPath, categoryNode.get() ); |
||||
|
|
||||
|
parent_iter->second->push_back( std::move( categoryNode ) ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* add_category wrapper. |
||||
|
* |
||||
|
* Function checks if path exists in the category and adds it if it doesn't. |
||||
|
* |
||||
|
* @param aCategoryPath is the std::string representation of the category. |
||||
|
* @param aCategoryStore is the CATEGORY_STORE instance to add to. |
||||
|
*/ |
||||
|
static void try_add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore ) |
||||
|
{ |
||||
|
if( !aCategoryStore.contains( aCategoryPath ) ) |
||||
|
{ |
||||
|
add_category( aCategoryPath, aCategoryStore ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_GERBVIEW_PLUGIN_IMPL::exportCommandsAndImages() |
||||
|
{ |
||||
|
wxLogTrace( m_logTrace, wxT( "NL_GERBVIEW_PLUGIN_IMPL::exportCommandsAndImages" ) ); |
||||
|
|
||||
|
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList(); |
||||
|
|
||||
|
if( actions.empty() ) |
||||
|
return; |
||||
|
|
||||
|
using TDx::SpaceMouse::CCommand; |
||||
|
using TDx::SpaceMouse::CCommandSet; |
||||
|
|
||||
|
// The root action set node
|
||||
|
CCommandSet commandSet( "GERBER_EDITOR", "Gerber Viewer" ); |
||||
|
|
||||
|
// Activate the command set
|
||||
|
NAV_3D::PutActiveCommands( commandSet.GetId() ); |
||||
|
|
||||
|
// temporary store for the categories initialized with action set
|
||||
|
CATEGORY_STORE categoryStore{ CATEGORY_STORE::value_type( ".", &commandSet ) }; |
||||
|
|
||||
|
std::vector<TDx::CImage> vImages; |
||||
|
|
||||
|
for( const auto action : actions ) |
||||
|
{ |
||||
|
std::string label = action->GetMenuLabel().ToStdString(); |
||||
|
|
||||
|
if( label.empty() ) |
||||
|
continue; |
||||
|
|
||||
|
std::string name = action->GetName(); |
||||
|
|
||||
|
// Do no export commands for the 3DViewer app.
|
||||
|
|
||||
|
if( name.rfind( "3DViewer.", 0 ) == 0 ) |
||||
|
continue; |
||||
|
|
||||
|
std::string strCategory = action->GetToolName(); |
||||
|
std::string description = action->GetDescription().ToStdString(); |
||||
|
|
||||
|
try_add_category( strCategory, categoryStore ); |
||||
|
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory ); |
||||
|
|
||||
|
// Arbitrary 8-bit data stream
|
||||
|
wxMemoryOutputStream imageStream; |
||||
|
|
||||
|
if( action->GetIcon() != BITMAPS::INVALID_BITMAP ) |
||||
|
{ |
||||
|
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage(); |
||||
|
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG ); |
||||
|
image.Destroy(); |
||||
|
|
||||
|
if( imageStream.GetSize() ) |
||||
|
{ |
||||
|
const wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer(); |
||||
|
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() ); |
||||
|
tdxImage.AssignImage( |
||||
|
std::string( std::bit_cast<const char*>( streamBuffer->GetBufferStart() ), |
||||
|
streamBuffer->GetBufferSize() ), |
||||
|
0 ); |
||||
|
|
||||
|
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name ); |
||||
|
vImages.push_back( std::move( tdxImage ) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ), |
||||
|
name, description, iter->first ); |
||||
|
|
||||
|
iter->second->push_back( |
||||
|
CCommand( std::move( name ), std::move( label ), std::move( description ) ) ); |
||||
|
} |
||||
|
|
||||
|
NAV_3D::AddCommandSet( commandSet ); |
||||
|
NAV_3D::AddImages( vImages ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
m_viewPosition = m_view->GetCenter(); |
||||
|
|
||||
|
double x = m_view->IsMirroredX() ? -1 : 1; |
||||
|
double y = m_view->IsMirroredY() ? 1 : -1; |
||||
|
|
||||
|
// x * y * z = 1 for a right-handed coordinate system.
|
||||
|
double z = x * y; |
||||
|
|
||||
|
// Note: the connexion has been configured as row vectors, the coordinate system is defined in
|
||||
|
// NL_GERBVIEW_PLUGIN_IMPL::GetCoordinateSystem and the front view in NL_GERBVIEW_PLUGIN_IMPL::GetFrontView.
|
||||
|
matrix = { { { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, m_viewPosition.x, m_viewPosition.y, 0, |
||||
|
1 } } }; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
VECTOR2D mouse_pointer = m_viewport2D->GetViewControls()->GetMousePosition(); |
||||
|
|
||||
|
position.x = mouse_pointer.x; |
||||
|
position.y = mouse_pointer.y; |
||||
|
position.z = 0; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
double scale = m_viewport2D->GetGAL()->GetWorldScale(); |
||||
|
BOX2D box = m_view->GetViewport(); |
||||
|
|
||||
|
m_viewportWidth = box.GetWidth(); |
||||
|
|
||||
|
extents.min_x = -box.GetWidth() / 2.0; |
||||
|
extents.min_y = -box.GetHeight() / 2.0; |
||||
|
extents.min_z = m_viewport2D->GetGAL()->GetMinDepth() / scale; |
||||
|
extents.max_x = box.GetWidth() / 2.0; |
||||
|
extents.max_y = box.GetHeight() / 2.0; |
||||
|
extents.max_z = m_viewport2D->GetGAL()->GetMaxDepth() / scale; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const |
||||
|
{ |
||||
|
perspective = false; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& matrix ) |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
|
||||
|
long result = 0; |
||||
|
VECTOR2D viewPos( matrix.m4x4[3][0], matrix.m4x4[3][1] ); |
||||
|
|
||||
|
if( !equals( m_view->GetCenter(), m_viewPosition, |
||||
|
static_cast<VECTOR2D::coord_type>( FLT_EPSILON ) ) ) |
||||
|
{ |
||||
|
m_view->SetCenter( viewPos + m_view->GetCenter() - m_viewPosition ); |
||||
|
result = navlib::make_result_code( navlib::navlib_errc::error ); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
m_view->SetCenter( viewPos ); |
||||
|
} |
||||
|
|
||||
|
m_viewPosition = viewPos; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents ) |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
|
||||
|
long result = 0; |
||||
|
|
||||
|
if( m_viewportWidth != m_view->GetViewport().GetWidth() ) |
||||
|
result = navlib::make_result_code( navlib::navlib_errc::error ); |
||||
|
|
||||
|
double width = m_viewportWidth; |
||||
|
m_viewportWidth = extents.max_x - extents.min_x; |
||||
|
|
||||
|
double scale = width / m_viewportWidth * m_view->GetScale(); |
||||
|
m_view->SetScale( scale, m_view->GetCenter() ); |
||||
|
|
||||
|
if( !equals( m_view->GetScale(), scale, static_cast<double>( FLT_EPSILON ) ) ) |
||||
|
result = navlib::make_result_code( navlib::navlib_errc::error ); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetViewFOV( double fov ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
BOX2I box = static_cast<GERBVIEW_FRAME*>( m_viewport2D->GetParent() )->GetDocumentExtents(); |
||||
|
box.Normalize(); |
||||
|
|
||||
|
double half_depth = 0.1 / m_viewport2D->GetGAL()->GetWorldScale(); |
||||
|
|
||||
|
if( box.GetWidth() == 0 && box.GetHeight() == 0 ) |
||||
|
half_depth = 0; |
||||
|
|
||||
|
extents.min_x = static_cast<double>( box.GetOrigin().x ); |
||||
|
extents.min_y = static_cast<double>( box.GetOrigin().y ); |
||||
|
extents.min_z = -half_depth; |
||||
|
extents.max_x = static_cast<double>( box.GetEnd().x ); |
||||
|
extents.max_y = static_cast<double>( box.GetEnd().y ); |
||||
|
extents.max_z = half_depth; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const |
||||
|
{ |
||||
|
// The coordinate system is defined as x to the right, y down and z into the screen.
|
||||
|
matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } }; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const |
||||
|
{ |
||||
|
matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } }; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetIsSelectionEmpty( navlib::bool_t& empty ) const |
||||
|
{ |
||||
|
empty = true; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const |
||||
|
{ |
||||
|
isRotatable = false; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetActiveCommand( std::string commandId ) |
||||
|
{ |
||||
|
if( commandId.empty() ) |
||||
|
return 0; |
||||
|
|
||||
|
if(m_viewport2D == nullptr) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
wxWindow* parent = m_viewport2D->GetParent(); |
||||
|
|
||||
|
// Only allow command execution if the window is enabled. i.e. there is not a modal dialog
|
||||
|
// currently active.
|
||||
|
if( parent == nullptr || !parent->IsEnabled() ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
TOOL_MANAGER* tool_manager = dynamic_cast<TOOLS_HOLDER*>( parent )->GetToolManager(); |
||||
|
|
||||
|
// Only allow for command execution if the tool manager is accessible.
|
||||
|
if( tool_manager == nullptr ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
for( std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList(); |
||||
|
const auto action : actions ) |
||||
|
{ |
||||
|
if( action == nullptr ) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if( commandId == action->GetName() ) |
||||
|
{ |
||||
|
// Get the selection to use to test if the action is enabled
|
||||
|
const SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection(); |
||||
|
|
||||
|
const ACTION_CONDITIONS* aCond = |
||||
|
tool_manager->GetActionManager()->GetCondition( *action ); |
||||
|
|
||||
|
if( aCond == nullptr ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
aCond->enableCondition( sel ); |
||||
|
tool_manager->RunAction( *action ); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetSettingsChanged( long change ) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetMotionFlag( bool value ) |
||||
|
{ |
||||
|
m_isMoving = value; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetTransaction( long value ) |
||||
|
{ |
||||
|
if( value == 0L ) |
||||
|
m_viewport2D->ForceRefresh(); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetViewFOV( double& fov ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& frustum ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetPivotVisible( bool visible ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetHitAperture( double aperture ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetHitSelectionOnly( bool onlySelection ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_GERBVIEW_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
@ -0,0 +1,147 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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/>. |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @file nl_gerbview_plugin_impl.h |
||||
|
* @brief Declaration of the NL_GERBVIEW_PLUGIN_IMPL class |
||||
|
*/ |
||||
|
|
||||
|
#ifndef NL_GERBVIEW_PLUGIN_IMPL_H_ |
||||
|
#define NL_GERBVIEW_PLUGIN_IMPL_H_ |
||||
|
|
||||
|
#if _WIN32 |
||||
|
#ifndef _WIN32_WINNT |
||||
|
#define _WIN32_WINNT 0x0603 |
||||
|
#endif |
||||
|
#endif |
||||
|
|
||||
|
// TDxWare SDK. |
||||
|
#include <SpaceMouse/CNavigation3D.hpp> |
||||
|
|
||||
|
// wx |
||||
|
#include <wx/chartype.h> |
||||
|
|
||||
|
// KiCAD |
||||
|
#include <math/vector2d.h> |
||||
|
|
||||
|
// stdlib |
||||
|
#include <string> |
||||
|
|
||||
|
// Forward declarations. |
||||
|
class EDA_DRAW_PANEL_GAL; |
||||
|
namespace KIGFX |
||||
|
{ |
||||
|
class VIEW; |
||||
|
} |
||||
|
|
||||
|
// Convenience typedef. |
||||
|
typedef TDx::SpaceMouse::Navigation3D::CNavigation3D NAV_3D; |
||||
|
|
||||
|
/** |
||||
|
* The class that implements the accessors and mutators required for |
||||
|
* 3D navigation in an PCB_DRAW_PANEL_GAL using a SpaceMouse. |
||||
|
*/ |
||||
|
class NL_GERBVIEW_PLUGIN_IMPL : public NAV_3D |
||||
|
{ |
||||
|
public: |
||||
|
/** |
||||
|
* Initializes a new instance of the NL_GERBVIEW_PLUGIN_IMPL. |
||||
|
*/ |
||||
|
NL_GERBVIEW_PLUGIN_IMPL(); |
||||
|
|
||||
|
|
||||
|
virtual ~NL_GERBVIEW_PLUGIN_IMPL(); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Sets the viewport controlled by the SpaceMouse. |
||||
|
* |
||||
|
* @param aViewport is the viewport to be navigated. |
||||
|
*/ |
||||
|
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Set the connection to the 3Dconnexion driver to the focus state so that |
||||
|
* 3DMouse data is routed here. |
||||
|
* |
||||
|
* @param aFocus is true to set the connection active. |
||||
|
*/ |
||||
|
void SetFocus( bool aFocus ); |
||||
|
|
||||
|
private: |
||||
|
/** |
||||
|
* Export the invocable actions and images to the 3Dconnexion UI. |
||||
|
*/ |
||||
|
void exportCommandsAndImages(); |
||||
|
|
||||
|
long GetCameraMatrix( navlib::matrix_t& aMatrix ) const override; |
||||
|
long GetPointerPosition( navlib::point_t& aPosition ) const override; |
||||
|
long GetViewExtents( navlib::box_t& aExtents ) const override; |
||||
|
long GetViewFOV( double& aFov ) const override; |
||||
|
long GetViewFrustum( navlib::frustum_t& aFrustum ) const override; |
||||
|
long GetIsViewPerspective( navlib::bool_t& aPerspective ) const override; |
||||
|
long SetCameraMatrix( const navlib::matrix_t& aMatrix ) override; |
||||
|
long SetViewExtents( const navlib::box_t& aExtents ) override; |
||||
|
long SetViewFOV( double aFov ) override; |
||||
|
long SetViewFrustum( const navlib::frustum_t& aFrustum ) override; |
||||
|
long GetModelExtents( navlib::box_t& aExtents ) const override; |
||||
|
long GetSelectionExtents( navlib::box_t& aExtents ) const override; |
||||
|
long GetSelectionTransform( navlib::matrix_t& aTransform ) const override; |
||||
|
long GetIsSelectionEmpty( navlib::bool_t& aEmpty ) const override; |
||||
|
long SetSelectionTransform( const navlib::matrix_t& aMatrix ) override; |
||||
|
long GetPivotPosition( navlib::point_t& aPosition ) const override; |
||||
|
long IsUserPivot( navlib::bool_t& aUserPivot ) const override; |
||||
|
long SetPivotPosition( const navlib::point_t& aPosition ) override; |
||||
|
long GetPivotVisible( navlib::bool_t& aVisible ) const override; |
||||
|
long SetPivotVisible( bool aVisible ) override; |
||||
|
long GetHitLookAt( navlib::point_t& aPosition ) const override; |
||||
|
long SetHitAperture( double aAperture ) override; |
||||
|
long SetHitDirection( const navlib::vector_t& aDirection ) override; |
||||
|
long SetHitLookFrom( const navlib::point_t& aPosition ) override; |
||||
|
long SetHitSelectionOnly( bool aSelectionOnly ) override; |
||||
|
long SetActiveCommand( std::string aCommandId ) override; |
||||
|
|
||||
|
long SetSettingsChanged( long aChangeNumber ) override; |
||||
|
long SetMotionFlag( bool aValue ) override; |
||||
|
long SetTransaction( long aValue ) override; |
||||
|
long SetCameraTarget( const navlib::point_t& aPosition ) override; |
||||
|
|
||||
|
long GetFrontView( navlib::matrix_t& aMatrix ) const override; |
||||
|
long GetCoordinateSystem( navlib::matrix_t& aMatrix ) const override; |
||||
|
long GetIsViewRotatable( navlib::bool_t& isRotatable ) const override; |
||||
|
|
||||
|
private: |
||||
|
EDA_DRAW_PANEL_GAL* m_viewport2D = nullptr; |
||||
|
KIGFX::VIEW* m_view = nullptr; |
||||
|
bool m_isMoving = false; |
||||
|
mutable double m_viewportWidth = 0.0; |
||||
|
mutable VECTOR2D m_viewPosition; |
||||
|
|
||||
|
/** |
||||
|
* Trace mask used to enable or disable the trace output of this class. |
||||
|
* The debug output can be turned on by setting the WXTRACE environment variable to |
||||
|
* "KI_TRACE_NL_GERBVIEW_PLUGIN". See the wxWidgets documentation on wxLogTrace for |
||||
|
* more information. |
||||
|
*/ |
||||
|
static const wxChar* m_logTrace; |
||||
|
}; |
||||
|
|
||||
|
#endif // NL_GERBVIEW_PLUGIN_IMPL |
@ -0,0 +1,25 @@ |
|||||
|
|
||||
|
add_library(pl_editor_navlib STATIC |
||||
|
"nl_pl_editor_plugin.cpp" |
||||
|
"nl_pl_editor_plugin_impl.cpp" |
||||
|
) |
||||
|
|
||||
|
# pl_editor_navlib depends on make_lexer outputs in common |
||||
|
add_dependencies( pl_editor_navlib common ) |
||||
|
|
||||
|
# Find the 3DxWare SDK component 3DxWare::NlClient |
||||
|
# find_package(TDxWare_SDK 4.0 REQUIRED COMPONENTS 3DxWare::Navlib) |
||||
|
target_compile_definitions(pl_editor_navlib PRIVATE |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_DEFINITIONS> |
||||
|
) |
||||
|
target_compile_options(pl_editor_navlib PRIVATE |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_OPTIONS> |
||||
|
) |
||||
|
target_include_directories(pl_editor_navlib PRIVATE |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_INCLUDE_DIRECTORIES> |
||||
|
$<TARGET_PROPERTY:pl_editor_kiface,INCLUDE_DIRECTORIES> |
||||
|
) |
||||
|
target_link_libraries(pl_editor_navlib |
||||
|
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_LINK_LIBRARIES> |
||||
|
3DxWare::Navlib |
||||
|
) |
@ -0,0 +1,52 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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 "nl_pl_editor_plugin.h"
|
||||
|
#include "nl_pl_editor_plugin_impl.h"
|
||||
|
|
||||
|
#include <advanced_config.h>
|
||||
|
#include <kiplatform/drivers.h>
|
||||
|
|
||||
|
|
||||
|
NL_PL_EDITOR_PLUGIN::NL_PL_EDITOR_PLUGIN() |
||||
|
{ |
||||
|
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver |
||||
|
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() ) |
||||
|
{ |
||||
|
m_impl = std::make_unique<NL_PL_EDITOR_PLUGIN_IMPL>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
NL_PL_EDITOR_PLUGIN::~NL_PL_EDITOR_PLUGIN() = default; |
||||
|
|
||||
|
|
||||
|
void NL_PL_EDITOR_PLUGIN::SetFocus( bool focus ) |
||||
|
{ |
||||
|
if( m_impl ) |
||||
|
m_impl->SetFocus( focus ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_PL_EDITOR_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ) |
||||
|
{ |
||||
|
if( m_impl ) |
||||
|
m_impl->SetCanvas( aViewport ); |
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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/>. |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @file nl_gerbview_plugin.h |
||||
|
* @brief Declaration of the NL_PL_EDITOR_PLUGIN class |
||||
|
*/ |
||||
|
|
||||
|
#ifndef NL_GERBVIEW_PLUGIN_H_ |
||||
|
#define NL_GERBVIEW_PLUGIN_H_ |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
// Forward declarations. |
||||
|
class EDA_DRAW_PANEL_GAL; |
||||
|
class NL_PL_EDITOR_PLUGIN_IMPL; |
||||
|
|
||||
|
/** |
||||
|
* The class that implements the public interface to the SpaceMouse plug-in. |
||||
|
*/ |
||||
|
class NL_PL_EDITOR_PLUGIN |
||||
|
{ |
||||
|
public: |
||||
|
/** |
||||
|
* Initializes a new instance of the NL_PL_EDITOR_PLUGIN. |
||||
|
*/ |
||||
|
NL_PL_EDITOR_PLUGIN(); |
||||
|
|
||||
|
virtual ~NL_PL_EDITOR_PLUGIN(); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Sets the viewport controlled by the SpaceMouse. |
||||
|
* |
||||
|
* @param aViewport is the viewport to be navigated. |
||||
|
*/ |
||||
|
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Set the connection to the 3Dconnexion driver to the focus state so that |
||||
|
* 3DMouse data is routed to this connexion. |
||||
|
* |
||||
|
* @param aFocus is true to set the connexion active. |
||||
|
*/ |
||||
|
void SetFocus( bool aFocus ); |
||||
|
|
||||
|
private: |
||||
|
std::unique_ptr<NL_PL_EDITOR_PLUGIN_IMPL> m_impl; |
||||
|
}; |
||||
|
|
||||
|
#endif // NL_GERBVIEW_PLUGIN_H_ |
@ -0,0 +1,598 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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 "nl_pl_editor_plugin_impl.h"
|
||||
|
|
||||
|
// KiCAD includes
|
||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||
|
#include <pl_editor_frame.h>
|
||||
|
#include <bitmaps.h>
|
||||
|
#include <class_draw_panel_gal.h>
|
||||
|
#include <view/view.h>
|
||||
|
#include <view/wx_view_controls.h>
|
||||
|
#include <tool/action_manager.h>
|
||||
|
#include <tool/tool_action.h>
|
||||
|
#include <tool/tool_manager.h>
|
||||
|
|
||||
|
// stdlib
|
||||
|
#include <list>
|
||||
|
#include <map>
|
||||
|
#include <memory>
|
||||
|
#include <utility>
|
||||
|
#include <vector>
|
||||
|
#include <cfloat>
|
||||
|
|
||||
|
#include <wx/log.h>
|
||||
|
#include <wx/mstream.h>
|
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Flag to enable the NL_PL_EDITOR_PLUGIN debug tracing. |
||||
|
* |
||||
|
* Use "KI_TRACE_NL_PL_EDITOR_PLUGIN" to enable. |
||||
|
* |
||||
|
* @ingroup trace_env_vars |
||||
|
*/ |
||||
|
const wxChar* NL_PL_EDITOR_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_PL_EDITOR_PLUGIN" ); |
||||
|
|
||||
|
|
||||
|
NL_PL_EDITOR_PLUGIN_IMPL::NL_PL_EDITOR_PLUGIN_IMPL() : CNavigation3D( false, false ) |
||||
|
{ |
||||
|
PutProfileHint( "KiCAD Datasheet Editor" ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
NL_PL_EDITOR_PLUGIN_IMPL::~NL_PL_EDITOR_PLUGIN_IMPL() |
||||
|
{ |
||||
|
std::error_code m_errCode; |
||||
|
EnableNavigation( false, m_errCode ); |
||||
|
if( m_errCode.value() != 0 ) |
||||
|
{ |
||||
|
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), |
||||
|
wxT( "Error occured when calling EnableNavigation. Error code: %d" ), |
||||
|
m_errCode.value() ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_PL_EDITOR_PLUGIN_IMPL::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ) |
||||
|
{ |
||||
|
m_viewport2D = aViewport; |
||||
|
|
||||
|
if( m_viewport2D == nullptr ) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
m_view = m_viewport2D->GetView(); |
||||
|
|
||||
|
if( m_view == nullptr ) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
m_viewportWidth = m_view->GetBoundary().GetWidth(); |
||||
|
|
||||
|
if( !IsEnabled() ) |
||||
|
{ |
||||
|
// Use the default settings for the connexion to the 3DMouse navigation
|
||||
|
// They are use a single-threaded threading model and row vectors.
|
||||
|
EnableNavigation( true ); |
||||
|
|
||||
|
// Use the SpaceMouse internal timing source for the frame rate.
|
||||
|
PutFrameTimingSource( TimingSource::SpaceMouse ); |
||||
|
|
||||
|
exportCommandsAndImages(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_PL_EDITOR_PLUGIN_IMPL::SetFocus( bool aFocus ) |
||||
|
{ |
||||
|
wxLogTrace( m_logTrace, wxT( "NL_PL_EDITOR_PLUGIN_IMPL::SetFocus %d" ), aFocus ); |
||||
|
NAV_3D::Write( navlib::focus_k, aFocus ); |
||||
|
} |
||||
|
|
||||
|
// temporary store for the command categories
|
||||
|
using CATEGORY_STORE = std::map<std::string, TDx::CCommandTreeNode*, std::less<>>; |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Add a category to the store. |
||||
|
* |
||||
|
* The function adds category paths of the format "A.B" where B is a sub-category of A. |
||||
|
* |
||||
|
* @param aCategoryPath is the std::string representation of the category. |
||||
|
* @param aCategoryStore is the CATEGORY_STORE instance to add to. |
||||
|
*/ |
||||
|
static void add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore ) |
||||
|
{ |
||||
|
using TDx::SpaceMouse::CCategory; |
||||
|
|
||||
|
auto parent_iter = aCategoryStore.begin(); |
||||
|
std::string::size_type pos = aCategoryPath.find_last_of( '.' ); |
||||
|
|
||||
|
if( pos != std::string::npos ) |
||||
|
{ |
||||
|
std::string parentPath = aCategoryPath.substr( 0, pos ); |
||||
|
|
||||
|
if( !aCategoryStore.contains( parentPath ) ) |
||||
|
{ |
||||
|
add_category( parentPath, aCategoryStore ); |
||||
|
parent_iter = aCategoryStore.find( parentPath ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
std::string name = aCategoryPath.substr( pos + 1 ); |
||||
|
auto categoryNode = std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() ); |
||||
|
|
||||
|
aCategoryStore.try_emplace( aCategoryStore.end(), aCategoryPath, categoryNode.get() ); |
||||
|
|
||||
|
parent_iter->second->push_back( std::move( categoryNode ) ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* add_category wrapper. |
||||
|
* |
||||
|
* Function checks if path exists in the category and adds it if it doesn't. |
||||
|
* |
||||
|
* @param aCategoryPath is the std::string representation of the category. |
||||
|
* @param aCategoryStore is the CATEGORY_STORE instance to add to. |
||||
|
*/ |
||||
|
static void try_add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore ) |
||||
|
{ |
||||
|
if( !aCategoryStore.contains( aCategoryPath ) ) |
||||
|
{ |
||||
|
add_category( aCategoryPath, aCategoryStore ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void NL_PL_EDITOR_PLUGIN_IMPL::exportCommandsAndImages() |
||||
|
{ |
||||
|
wxLogTrace( m_logTrace, wxT( "NL_PL_EDITOR_PLUGIN_IMPL::exportCommandsAndImages" ) ); |
||||
|
|
||||
|
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList(); |
||||
|
|
||||
|
if( actions.empty() ) |
||||
|
return; |
||||
|
|
||||
|
using TDx::SpaceMouse::CCommand; |
||||
|
using TDx::SpaceMouse::CCommandSet; |
||||
|
|
||||
|
// The root action set node
|
||||
|
CCommandSet commandSet( "PL_EDITOR", "Drawing Sheet Editor" ); |
||||
|
|
||||
|
// Activate the command set
|
||||
|
NAV_3D::PutActiveCommands( commandSet.GetId() ); |
||||
|
|
||||
|
// temporary store for the categories initialized with action set
|
||||
|
CATEGORY_STORE categoryStore{ CATEGORY_STORE::value_type( ".", &commandSet ) }; |
||||
|
|
||||
|
std::vector<TDx::CImage> vImages; |
||||
|
|
||||
|
for( const auto action : actions ) |
||||
|
{ |
||||
|
std::string label = action->GetMenuLabel().ToStdString(); |
||||
|
|
||||
|
if( label.empty() ) |
||||
|
continue; |
||||
|
|
||||
|
std::string name = action->GetName(); |
||||
|
|
||||
|
// Do no export commands for the 3DViewer app.
|
||||
|
|
||||
|
if( name.rfind( "3DViewer.", 0 ) == 0 ) |
||||
|
continue; |
||||
|
|
||||
|
std::string strCategory = action->GetToolName(); |
||||
|
std::string description = action->GetDescription().ToStdString(); |
||||
|
|
||||
|
try_add_category( strCategory, categoryStore ); |
||||
|
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory ); |
||||
|
|
||||
|
// Arbitrary 8-bit data stream
|
||||
|
wxMemoryOutputStream imageStream; |
||||
|
|
||||
|
if( action->GetIcon() != BITMAPS::INVALID_BITMAP ) |
||||
|
{ |
||||
|
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage(); |
||||
|
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG ); |
||||
|
image.Destroy(); |
||||
|
|
||||
|
if( imageStream.GetSize() ) |
||||
|
{ |
||||
|
const wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer(); |
||||
|
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() ); |
||||
|
tdxImage.AssignImage( |
||||
|
std::string( std::bit_cast<const char*>( streamBuffer->GetBufferStart() ), |
||||
|
streamBuffer->GetBufferSize() ), |
||||
|
0 ); |
||||
|
|
||||
|
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name ); |
||||
|
vImages.push_back( std::move( tdxImage ) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ), |
||||
|
name, description, iter->first ); |
||||
|
|
||||
|
iter->second->push_back( |
||||
|
CCommand( std::move( name ), std::move( label ), std::move( description ) ) ); |
||||
|
} |
||||
|
|
||||
|
NAV_3D::AddCommandSet( commandSet ); |
||||
|
NAV_3D::AddImages( vImages ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
m_viewPosition = m_view->GetCenter(); |
||||
|
|
||||
|
double x = m_view->IsMirroredX() ? -1 : 1; |
||||
|
double y = m_view->IsMirroredY() ? 1 : -1; |
||||
|
|
||||
|
// x * y * z = 1 for a right-handed coordinate system.
|
||||
|
double z = x * y; |
||||
|
|
||||
|
// Note: the connexion has been configured as row vectors, the coordinate system is defined in
|
||||
|
// NL_PL_EDITOR_PLUGIN_IMPL::GetCoordinateSystem and the front view in NL_PL_EDITOR_PLUGIN_IMPL::GetFrontView.
|
||||
|
matrix = { { { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, m_viewPosition.x, m_viewPosition.y, 0, |
||||
|
1 } } }; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
VECTOR2D mouse_pointer = m_viewport2D->GetViewControls()->GetMousePosition(); |
||||
|
|
||||
|
position.x = mouse_pointer.x; |
||||
|
position.y = mouse_pointer.y; |
||||
|
position.z = 0; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
double scale = m_viewport2D->GetGAL()->GetWorldScale(); |
||||
|
BOX2D box = m_view->GetViewport(); |
||||
|
|
||||
|
m_viewportWidth = box.GetWidth(); |
||||
|
|
||||
|
extents.min_x = -box.GetWidth() / 2.0; |
||||
|
extents.min_y = -box.GetHeight() / 2.0; |
||||
|
extents.min_z = m_viewport2D->GetGAL()->GetMinDepth() / scale; |
||||
|
extents.max_x = box.GetWidth() / 2.0; |
||||
|
extents.max_y = box.GetHeight() / 2.0; |
||||
|
extents.max_z = m_viewport2D->GetGAL()->GetMaxDepth() / scale; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const |
||||
|
{ |
||||
|
perspective = false; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& matrix ) |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
|
||||
|
long result = 0; |
||||
|
VECTOR2D viewPos( matrix.m4x4[3][0], matrix.m4x4[3][1] ); |
||||
|
|
||||
|
if( !equals( m_view->GetCenter(), m_viewPosition, |
||||
|
static_cast<VECTOR2D::coord_type>( FLT_EPSILON ) ) ) |
||||
|
{ |
||||
|
m_view->SetCenter( viewPos + m_view->GetCenter() - m_viewPosition ); |
||||
|
result = navlib::make_result_code( navlib::navlib_errc::error ); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
m_view->SetCenter( viewPos ); |
||||
|
} |
||||
|
|
||||
|
m_viewPosition = viewPos; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents ) |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
|
||||
|
long result = 0; |
||||
|
|
||||
|
if( m_viewportWidth != m_view->GetViewport().GetWidth() ) |
||||
|
result = navlib::make_result_code( navlib::navlib_errc::error ); |
||||
|
|
||||
|
double width = m_viewportWidth; |
||||
|
m_viewportWidth = extents.max_x - extents.min_x; |
||||
|
|
||||
|
double scale = width / m_viewportWidth * m_view->GetScale(); |
||||
|
m_view->SetScale( scale, m_view->GetCenter() ); |
||||
|
|
||||
|
if( !equals( m_view->GetScale(), scale, static_cast<double>( FLT_EPSILON ) ) ) |
||||
|
result = navlib::make_result_code( navlib::navlib_errc::error ); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetViewFOV( double fov ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const |
||||
|
{ |
||||
|
if( m_view == nullptr ) |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
|
||||
|
BOX2I box = static_cast<PL_EDITOR_FRAME*>( m_viewport2D->GetParent() )->GetDocumentExtents(); |
||||
|
box.Normalize(); |
||||
|
|
||||
|
double half_depth = 0.1 / m_viewport2D->GetGAL()->GetWorldScale(); |
||||
|
|
||||
|
if( box.GetWidth() == 0 && box.GetHeight() == 0 ) |
||||
|
half_depth = 0; |
||||
|
|
||||
|
extents.min_x = static_cast<double>( box.GetOrigin().x ); |
||||
|
extents.min_y = static_cast<double>( box.GetOrigin().y ); |
||||
|
extents.min_z = -half_depth; |
||||
|
extents.max_x = static_cast<double>( box.GetEnd().x ); |
||||
|
extents.max_y = static_cast<double>( box.GetEnd().y ); |
||||
|
extents.max_z = half_depth; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const |
||||
|
{ |
||||
|
// The coordinate system is defined as x to the right, y down and z into the screen.
|
||||
|
matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } }; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const |
||||
|
{ |
||||
|
matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } }; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetIsSelectionEmpty( navlib::bool_t& empty ) const |
||||
|
{ |
||||
|
empty = true; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const |
||||
|
{ |
||||
|
isRotatable = false; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetActiveCommand( std::string commandId ) |
||||
|
{ |
||||
|
if( commandId.empty() ) |
||||
|
return 0; |
||||
|
|
||||
|
if(m_viewport2D == nullptr) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
wxWindow* parent = m_viewport2D->GetParent(); |
||||
|
|
||||
|
// Only allow command execution if the window is enabled. i.e. there is not a modal dialog
|
||||
|
// currently active.
|
||||
|
if( parent == nullptr || !parent->IsEnabled() ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
TOOL_MANAGER* tool_manager = dynamic_cast<TOOLS_HOLDER*>( parent )->GetToolManager(); |
||||
|
|
||||
|
// Only allow for command execution if the tool manager is accessible.
|
||||
|
if( tool_manager == nullptr ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
for( std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList(); |
||||
|
const auto action : actions ) |
||||
|
{ |
||||
|
if( action == nullptr ) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if( commandId == action->GetName() ) |
||||
|
{ |
||||
|
// Get the selection to use to test if the action is enabled
|
||||
|
const SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection(); |
||||
|
|
||||
|
const ACTION_CONDITIONS* aCond = |
||||
|
tool_manager->GetActionManager()->GetCondition( *action ); |
||||
|
|
||||
|
if( aCond == nullptr ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
aCond->enableCondition( sel ); |
||||
|
tool_manager->RunAction( *action ); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetSettingsChanged( long change ) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetMotionFlag( bool value ) |
||||
|
{ |
||||
|
m_isMoving = value; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetTransaction( long value ) |
||||
|
{ |
||||
|
if( value == 0L ) |
||||
|
m_viewport2D->ForceRefresh(); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetViewFOV( double& fov ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& frustum ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetPivotVisible( bool visible ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetHitAperture( double aperture ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetHitSelectionOnly( bool onlySelection ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
long NL_PL_EDITOR_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position ) |
||||
|
{ |
||||
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation ); |
||||
|
} |
@ -0,0 +1,147 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2024 3Dconnexion |
||||
|
* Copyright (C) 2022 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/>. |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @file nl_gerbview_plugin_impl.h |
||||
|
* @brief Declaration of the NL_PL_EDITOR_PLUGIN_IMPL class |
||||
|
*/ |
||||
|
|
||||
|
#ifndef NL_GERBVIEW_PLUGIN_IMPL_H_ |
||||
|
#define NL_GERBVIEW_PLUGIN_IMPL_H_ |
||||
|
|
||||
|
#if _WIN32 |
||||
|
#ifndef _WIN32_WINNT |
||||
|
#define _WIN32_WINNT 0x0603 |
||||
|
#endif |
||||
|
#endif |
||||
|
|
||||
|
// TDxWare SDK. |
||||
|
#include <SpaceMouse/CNavigation3D.hpp> |
||||
|
|
||||
|
// wx |
||||
|
#include <wx/chartype.h> |
||||
|
|
||||
|
// KiCAD |
||||
|
#include <math/vector2d.h> |
||||
|
|
||||
|
// stdlib |
||||
|
#include <string> |
||||
|
|
||||
|
// Forward declarations. |
||||
|
class EDA_DRAW_PANEL_GAL; |
||||
|
namespace KIGFX |
||||
|
{ |
||||
|
class VIEW; |
||||
|
} |
||||
|
|
||||
|
// Convenience typedef. |
||||
|
typedef TDx::SpaceMouse::Navigation3D::CNavigation3D NAV_3D; |
||||
|
|
||||
|
/** |
||||
|
* The class that implements the accessors and mutators required for |
||||
|
* 3D navigation in an PCB_DRAW_PANEL_GAL using a SpaceMouse. |
||||
|
*/ |
||||
|
class NL_PL_EDITOR_PLUGIN_IMPL : public NAV_3D |
||||
|
{ |
||||
|
public: |
||||
|
/** |
||||
|
* Initializes a new instance of the NL_PL_EDITOR_PLUGIN_IMPL. |
||||
|
*/ |
||||
|
NL_PL_EDITOR_PLUGIN_IMPL(); |
||||
|
|
||||
|
|
||||
|
virtual ~NL_PL_EDITOR_PLUGIN_IMPL(); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Sets the viewport controlled by the SpaceMouse. |
||||
|
* |
||||
|
* @param aViewport is the viewport to be navigated. |
||||
|
*/ |
||||
|
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Set the connection to the 3Dconnexion driver to the focus state so that |
||||
|
* 3DMouse data is routed here. |
||||
|
* |
||||
|
* @param aFocus is true to set the connection active. |
||||
|
*/ |
||||
|
void SetFocus( bool aFocus ); |
||||
|
|
||||
|
private: |
||||
|
/** |
||||
|
* Export the invocable actions and images to the 3Dconnexion UI. |
||||
|
*/ |
||||
|
void exportCommandsAndImages(); |
||||
|
|
||||
|
long GetCameraMatrix( navlib::matrix_t& aMatrix ) const override; |
||||
|
long GetPointerPosition( navlib::point_t& aPosition ) const override; |
||||
|
long GetViewExtents( navlib::box_t& aExtents ) const override; |
||||
|
long GetViewFOV( double& aFov ) const override; |
||||
|
long GetViewFrustum( navlib::frustum_t& aFrustum ) const override; |
||||
|
long GetIsViewPerspective( navlib::bool_t& aPerspective ) const override; |
||||
|
long SetCameraMatrix( const navlib::matrix_t& aMatrix ) override; |
||||
|
long SetViewExtents( const navlib::box_t& aExtents ) override; |
||||
|
long SetViewFOV( double aFov ) override; |
||||
|
long SetViewFrustum( const navlib::frustum_t& aFrustum ) override; |
||||
|
long GetModelExtents( navlib::box_t& aExtents ) const override; |
||||
|
long GetSelectionExtents( navlib::box_t& aExtents ) const override; |
||||
|
long GetSelectionTransform( navlib::matrix_t& aTransform ) const override; |
||||
|
long GetIsSelectionEmpty( navlib::bool_t& aEmpty ) const override; |
||||
|
long SetSelectionTransform( const navlib::matrix_t& aMatrix ) override; |
||||
|
long GetPivotPosition( navlib::point_t& aPosition ) const override; |
||||
|
long IsUserPivot( navlib::bool_t& aUserPivot ) const override; |
||||
|
long SetPivotPosition( const navlib::point_t& aPosition ) override; |
||||
|
long GetPivotVisible( navlib::bool_t& aVisible ) const override; |
||||
|
long SetPivotVisible( bool aVisible ) override; |
||||
|
long GetHitLookAt( navlib::point_t& aPosition ) const override; |
||||
|
long SetHitAperture( double aAperture ) override; |
||||
|
long SetHitDirection( const navlib::vector_t& aDirection ) override; |
||||
|
long SetHitLookFrom( const navlib::point_t& aPosition ) override; |
||||
|
long SetHitSelectionOnly( bool aSelectionOnly ) override; |
||||
|
long SetActiveCommand( std::string aCommandId ) override; |
||||
|
|
||||
|
long SetSettingsChanged( long aChangeNumber ) override; |
||||
|
long SetMotionFlag( bool aValue ) override; |
||||
|
long SetTransaction( long aValue ) override; |
||||
|
long SetCameraTarget( const navlib::point_t& aPosition ) override; |
||||
|
|
||||
|
long GetFrontView( navlib::matrix_t& aMatrix ) const override; |
||||
|
long GetCoordinateSystem( navlib::matrix_t& aMatrix ) const override; |
||||
|
long GetIsViewRotatable( navlib::bool_t& isRotatable ) const override; |
||||
|
|
||||
|
private: |
||||
|
EDA_DRAW_PANEL_GAL* m_viewport2D = nullptr; |
||||
|
KIGFX::VIEW* m_view = nullptr; |
||||
|
bool m_isMoving = false; |
||||
|
mutable double m_viewportWidth = 0.0; |
||||
|
mutable VECTOR2D m_viewPosition; |
||||
|
|
||||
|
/** |
||||
|
* Trace mask used to enable or disable the trace output of this class. |
||||
|
* The debug output can be turned on by setting the WXTRACE environment variable to |
||||
|
* "KI_TRACE_NL_GERBVIEW_PLUGIN". See the wxWidgets documentation on wxLogTrace for |
||||
|
* more information. |
||||
|
*/ |
||||
|
static const wxChar* m_logTrace; |
||||
|
}; |
||||
|
|
||||
|
#endif // NL_PL_EDITOR_PLUGIN_IMPL |
Write
Preview
Loading…
Cancel
Save
Reference in new issue