2021-06-24 08:47:28 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2021 3Dconnexion
|
|
|
|
* Copyright (C) 2021 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_3d_viewer_plugin_impl.h"
|
|
|
|
|
|
|
|
// 3d-viewer
|
|
|
|
#include <3d-viewer/3d_rendering/track_ball.h>
|
|
|
|
#include <3d-viewer/3d_canvas/eda_3d_canvas.h>
|
|
|
|
|
|
|
|
// KiCAD includes
|
|
|
|
#include <tool/action_manager.h>
|
|
|
|
#include <tool/tool_manager.h>
|
|
|
|
|
|
|
|
// stdlib
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <wx/mstream.h>
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
/**
|
|
|
|
* Flag to enable the NL_3D_VIEWER_PLUGIN debug tracing.
|
|
|
|
*
|
|
|
|
* Use "KI_TRACE_NL_3D_VIEWER_PLUGIN" to enable.
|
|
|
|
*
|
|
|
|
* @ingroup trace_env_vars
|
|
|
|
*/
|
|
|
|
const wxChar* NL_3D_VIEWER_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_3D_VIEWER_PLUGIN" );
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Template to compare two glm::mat<T> values for equality within a required epsilon.
|
|
|
|
*
|
|
|
|
* @param aFirst value to compare.
|
|
|
|
* @param aSecond value to compare.
|
|
|
|
* @param aEpsilon allowed error.
|
|
|
|
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
|
|
|
*/
|
|
|
|
template <glm::length_t L, glm::length_t C, class T, glm::qualifier Q>
|
|
|
|
bool equals( glm::mat<L, C, T, Q> const& aFirst, glm::mat<L, C, T, Q> const& aSecond,
|
|
|
|
T aEpsilon = static_cast<T>( FLT_EPSILON * 10 ) )
|
|
|
|
{
|
|
|
|
T const* first = glm::value_ptr( aFirst );
|
|
|
|
T const* second = glm::value_ptr( aSecond );
|
|
|
|
|
|
|
|
for( glm::length_t j = 0; j < L * C; ++j )
|
|
|
|
{
|
|
|
|
if( !equals( first[j], second[j], aEpsilon ) )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
NL_3D_VIEWER_PLUGIN_IMPL::NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas ) :
|
2023-05-12 15:57:03 +00:00
|
|
|
NAV_3D( false, false ),
|
|
|
|
m_canvas( aCanvas ),
|
|
|
|
m_capIsMoving( false ),
|
|
|
|
m_newWidth( 0.0 )
|
2021-06-24 08:47:28 +00:00
|
|
|
{
|
|
|
|
m_camera = dynamic_cast<TRACK_BALL*>( m_canvas->GetCamera() );
|
|
|
|
|
|
|
|
PutProfileHint( "KiCAD 3D" );
|
|
|
|
|
|
|
|
EnableNavigation( true );
|
|
|
|
PutFrameTimingSource( TimingSource::SpaceMouse );
|
|
|
|
|
|
|
|
exportCommandsAndImages();
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
NL_3D_VIEWER_PLUGIN_IMPL::~NL_3D_VIEWER_PLUGIN_IMPL()
|
|
|
|
{
|
|
|
|
EnableNavigation( false );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
void NL_3D_VIEWER_PLUGIN_IMPL::SetFocus( bool aFocus )
|
|
|
|
{
|
|
|
|
wxLogTrace( m_logTrace, wxT( "NL_3D_VIEWER_PLUGIN_IMPL::SetFocus %d" ), aFocus );
|
|
|
|
NAV_3D::Write( navlib::focus_k, aFocus );
|
|
|
|
}
|
|
|
|
|
|
|
|
// temporary store for the categories
|
|
|
|
typedef std::map<std::string, TDx::CCommandTreeNode*> CATEGORY_STORE;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
* @return a CATEGORY_STORE::iterator where the category was added.
|
|
|
|
*/
|
|
|
|
CATEGORY_STORE::iterator add_category( std::string aCategoryPath, CATEGORY_STORE& aCategoryStore )
|
|
|
|
{
|
|
|
|
using TDx::SpaceMouse::CCategory;
|
|
|
|
|
|
|
|
CATEGORY_STORE::iterator 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 );
|
|
|
|
parent_iter = aCategoryStore.find( parentPath );
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( parent_iter == aCategoryStore.end() )
|
|
|
|
{
|
|
|
|
parent_iter = add_category( parentPath, aCategoryStore );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string name = aCategoryPath.substr( pos + 1 );
|
|
|
|
std::unique_ptr<CCategory> categoryNode =
|
|
|
|
std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() );
|
|
|
|
|
|
|
|
CATEGORY_STORE::iterator iter = aCategoryStore.insert(
|
|
|
|
aCategoryStore.end(), CATEGORY_STORE::value_type( aCategoryPath, categoryNode.get() ) );
|
|
|
|
|
|
|
|
parent_iter->second->push_back( std::move( categoryNode ) );
|
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
void NL_3D_VIEWER_PLUGIN_IMPL::exportCommandsAndImages()
|
|
|
|
{
|
|
|
|
wxLogTrace( m_logTrace, wxT( "NL_3D_VIEWER_PLUGIN_IMPL::exportCommandsAndImages" ) );
|
|
|
|
|
|
|
|
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
|
|
|
|
|
|
|
if( actions.size() == 0 )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
using TDx::SpaceMouse::CCommand;
|
|
|
|
using TDx::SpaceMouse::CCommandSet;
|
|
|
|
|
|
|
|
// The root action set node
|
|
|
|
CCommandSet commandSet( "EDA_3D_CANVAS", "3D Viewer" );
|
|
|
|
|
|
|
|
// Activate the command set
|
|
|
|
NAV_3D::PutActiveCommands( commandSet.GetId() );
|
|
|
|
|
|
|
|
// temporary store for the categories
|
|
|
|
CATEGORY_STORE categoryStore;
|
|
|
|
|
|
|
|
std::vector<TDx::CImage> vImages;
|
|
|
|
|
|
|
|
// add the action set to the category_store
|
2022-01-31 08:25:49 +00:00
|
|
|
categoryStore.insert( categoryStore.end(), CATEGORY_STORE::value_type( ".", &commandSet ) );
|
2021-06-24 08:47:28 +00:00
|
|
|
|
|
|
|
std::list<TOOL_ACTION*>::const_iterator it;
|
|
|
|
|
|
|
|
for( it = actions.begin(); it != actions.end(); ++it )
|
|
|
|
{
|
|
|
|
const TOOL_ACTION* action = *it;
|
2023-10-27 22:40:35 +00:00
|
|
|
std::string label = action->GetMenuLabel().ToStdString();
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( label.empty() )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string name = action->GetName();
|
|
|
|
|
|
|
|
// Do no export commands for the pcbnew app.
|
|
|
|
if( name.rfind( "pcbnew.", 0 ) == 0 )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string strCategory = action->GetToolName();
|
|
|
|
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( iter == categoryStore.end() )
|
|
|
|
{
|
|
|
|
iter = add_category( std::move( strCategory ), categoryStore );
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string description = action->GetDescription().ToStdString();
|
|
|
|
|
|
|
|
// Arbitrary 8-bit data stream
|
|
|
|
wxMemoryOutputStream imageStream;
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
|
|
|
|
{
|
|
|
|
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
|
|
|
|
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
|
|
|
|
image.Destroy();
|
|
|
|
|
|
|
|
if( imageStream.GetSize() )
|
|
|
|
{
|
|
|
|
wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
|
2022-01-31 08:25:49 +00:00
|
|
|
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
|
|
|
|
tdxImage.AssignImage( std::string( reinterpret_cast<const char*>(
|
|
|
|
streamBuffer->GetBufferStart() ),
|
|
|
|
streamBuffer->GetBufferSize() ),
|
|
|
|
0 );
|
2021-06-24 08:47:28 +00:00
|
|
|
|
2022-03-31 19:03:41 +00:00
|
|
|
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
2022-01-31 08:25:49 +00:00
|
|
|
vImages.push_back( std::move( tdxImage ) );
|
2021-06-24 08:47:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-31 19:03:41 +00:00
|
|
|
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
|
|
|
name, description, iter->first );
|
2021-06-24 08:47:28 +00:00
|
|
|
|
|
|
|
iter->second->push_back(
|
|
|
|
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
NAV_3D::AddCommandSet( commandSet );
|
|
|
|
NAV_3D::AddImages( vImages );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const
|
|
|
|
{
|
|
|
|
// cache the camera matrix so that we can tell if the view has been moved and
|
|
|
|
// calculate a delta transform if required.
|
|
|
|
m_cameraMatrix = m_camera->GetViewMatrix();
|
|
|
|
|
|
|
|
std::copy_n( glm::value_ptr( glm::inverse( m_cameraMatrix ) ), 16, matrix.m );
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const
|
|
|
|
{
|
|
|
|
SFVEC3F origin, direction;
|
|
|
|
m_camera->MakeRayAtCurrentMousePosition( origin, direction );
|
|
|
|
|
|
|
|
position = { origin.x, origin.y, origin.z };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const
|
|
|
|
{
|
|
|
|
if( m_camera->GetProjection() == PROJECTION_TYPE::PERSPECTIVE )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
|
|
|
}
|
|
|
|
|
|
|
|
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
|
|
|
|
|
|
|
double half_width = f.fw / 2.;
|
|
|
|
double half_height = f.fh / 2.;
|
|
|
|
extents = { -half_width, -half_height, f.nearD, half_width, half_height, f.farD };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetViewFOV( double& aFov ) const
|
|
|
|
{
|
|
|
|
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
|
|
|
|
|
|
|
aFov = glm::radians( f.angle );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& aFrustum ) const
|
|
|
|
{
|
|
|
|
if( m_camera->GetProjection() != PROJECTION_TYPE::PERSPECTIVE )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
|
|
|
}
|
|
|
|
|
|
|
|
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
|
|
|
double half_width = f.nw / 2.;
|
|
|
|
double half_height = f.nh / 2.;
|
|
|
|
aFrustum = { -half_width, half_width, -half_height, half_height, f.nearD, f.farD };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const
|
|
|
|
{
|
|
|
|
perspective = m_camera->GetProjection() == PROJECTION_TYPE::PERSPECTIVE ? 1 : 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& aCameraMatrix )
|
|
|
|
{
|
|
|
|
long result = 0;
|
|
|
|
|
|
|
|
glm::mat4 cam, viewMatrix;
|
|
|
|
std::copy_n( aCameraMatrix.m, 16, glm::value_ptr( cam ) );
|
|
|
|
viewMatrix = glm::inverse( cam );
|
|
|
|
|
|
|
|
glm::mat4 camera = m_camera->GetViewMatrix();
|
|
|
|
|
|
|
|
// The navlib does not move the camera in its z-axis in an orthographic projection
|
|
|
|
// as this does not change the viewed object size. However ...
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( m_camera->GetProjection() == PROJECTION_TYPE::ORTHO )
|
|
|
|
{
|
|
|
|
// ... the CAMERA class couples zoom and distance to the object: we need to
|
|
|
|
// ensure that The CAMERA's z position relative to the lookat_pos is not changed
|
|
|
|
// in an orthographic projection.
|
|
|
|
glm::vec4 lookat( m_camera->GetLookAtPos(), 1.0f );
|
|
|
|
glm::vec4 lookat_new = viewMatrix * lookat;
|
|
|
|
glm::vec4 lookat_old = camera * lookat;
|
|
|
|
|
|
|
|
viewMatrix[3].z += lookat_old.z - lookat_new.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !equals( camera, m_cameraMatrix ) )
|
|
|
|
{
|
|
|
|
// Some other input device has moved the camera. Apply only the intended delta
|
|
|
|
// transform ...
|
|
|
|
m_camera->SetViewMatrix( viewMatrix * glm::inverse( m_cameraMatrix ) * camera );
|
|
|
|
m_camera->Update();
|
|
|
|
|
|
|
|
// .., cache the intended camera matrix so that we can calculate the delta
|
|
|
|
// transform when needed ...
|
|
|
|
m_cameraMatrix = viewMatrix;
|
|
|
|
|
|
|
|
// ... and let the 3DMouse controller know, that something is amiss.
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::error );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_camera->SetViewMatrix( viewMatrix );
|
|
|
|
m_camera->Update();
|
|
|
|
|
|
|
|
// cache the view matrix so that we know when it has changed.
|
|
|
|
m_cameraMatrix = m_camera->GetViewMatrix();
|
|
|
|
|
|
|
|
// The camera has a constraint on the z position so we need to check that ...
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( !equals( m_cameraMatrix[3].z, viewMatrix[3].z ) )
|
|
|
|
{
|
|
|
|
// ... and let the 3DMouse controller know, when something is amiss.
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::error );
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents )
|
|
|
|
{
|
|
|
|
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
|
|
|
|
2022-02-01 13:17:30 +00:00
|
|
|
float factor = f.nw / ( extents.max_x - extents.min_x );
|
2021-06-24 08:47:28 +00:00
|
|
|
float zoom = m_camera->GetZoom() / factor;
|
|
|
|
|
|
|
|
m_camera->Zoom( factor );
|
|
|
|
|
|
|
|
// The camera auto positions the camera to match the zoom values. We need to
|
|
|
|
// update our cached camera matrix to match the new z value
|
|
|
|
m_cameraMatrix[3].z = m_camera->GetViewMatrix()[3].z;
|
|
|
|
|
|
|
|
// The camera has a constraint on the zoom factor so we need to check that ...
|
|
|
|
if( zoom != m_camera->GetZoom() )
|
|
|
|
{
|
|
|
|
// ... and let the 3DMouse controller know, when something is amiss.
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::error );
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetViewFOV( double fov )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::permission_denied );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
|
|
|
|
{
|
|
|
|
SFVEC3F min = m_canvas->GetBoardAdapter().GetBBox().Min();
|
|
|
|
SFVEC3F max = m_canvas->GetBoardAdapter().GetBBox().Max();
|
|
|
|
|
|
|
|
extents = { min.x, min.y, min.z, max.x, max.y, max.z };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetIsSelectionEmpty( navlib::bool_t& empty ) const
|
|
|
|
{
|
|
|
|
empty = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const
|
|
|
|
{
|
|
|
|
SFVEC3F lap = m_camera->GetLookAtPos();
|
|
|
|
|
|
|
|
position = { lap.x, lap.y, lap.z };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const
|
|
|
|
{
|
|
|
|
userPivot = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position )
|
|
|
|
{
|
|
|
|
SFVEC3F pivotPos = SFVEC3F( position.x, position.y, position.z );
|
|
|
|
|
2022-08-11 07:40:08 +00:00
|
|
|
// Set the 3dmouse pivot position.
|
|
|
|
m_canvas->Set3dmousePivotPos( pivotPos );
|
2021-06-24 08:47:28 +00:00
|
|
|
|
2022-08-11 07:40:08 +00:00
|
|
|
// Set the camera lookat pos.
|
|
|
|
m_camera->SetLookAtPos_T1( pivotPos );
|
2021-06-24 08:47:28 +00:00
|
|
|
|
|
|
|
m_canvas->Request_refresh();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const
|
|
|
|
{
|
2022-08-11 07:40:08 +00:00
|
|
|
visible = m_canvas->GetRender3dmousePivot();
|
2021-06-24 08:47:28 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetPivotVisible( bool visible )
|
|
|
|
{
|
2022-08-11 07:40:08 +00:00
|
|
|
m_canvas->SetRender3dmousePivot( visible );
|
2021-06-24 08:47:28 +00:00
|
|
|
|
|
|
|
m_canvas->Request_refresh();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const
|
|
|
|
{
|
|
|
|
RAY mouseRay;
|
|
|
|
mouseRay.Init( m_rayOrigin, m_rayDirection );
|
|
|
|
|
|
|
|
float hit;
|
|
|
|
glm::vec3 vec;
|
|
|
|
|
|
|
|
// Test it with the board bounding box
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( m_canvas->GetBoardAdapter().GetBBox().Intersect( mouseRay, &hit ) )
|
|
|
|
{
|
|
|
|
vec = mouseRay.at( hit );
|
|
|
|
position = { vec.x, vec.y, vec.z };
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitAperture( double aperture )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction )
|
|
|
|
{
|
|
|
|
m_rayDirection = { direction.x, direction.y, direction.z };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye )
|
|
|
|
{
|
|
|
|
m_rayOrigin = { eye.x, eye.y, eye.z };
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitSelectionOnly( bool onlySelection )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetActiveCommand( std::string commandId )
|
|
|
|
{
|
|
|
|
if( commandId.empty() )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
|
|
|
TOOL_ACTION* context = nullptr;
|
|
|
|
|
|
|
|
for( std::list<TOOL_ACTION*>::const_iterator it = actions.begin(); it != actions.end(); it++ )
|
|
|
|
{
|
|
|
|
TOOL_ACTION* action = *it;
|
|
|
|
std::string nm = action->GetName();
|
|
|
|
|
|
|
|
if( commandId == nm )
|
|
|
|
{
|
|
|
|
context = action;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( context != nullptr )
|
|
|
|
{
|
|
|
|
wxWindow* parent = m_canvas->GetParent();
|
|
|
|
|
|
|
|
// Only allow command execution if the window is enabled. i.e. there is not a modal dialog
|
|
|
|
// currently active.
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
if( parent->IsEnabled() )
|
|
|
|
{
|
|
|
|
TOOL_MANAGER* tool_manager = static_cast<PCB_BASE_FRAME*>( parent )->GetToolManager();
|
|
|
|
|
|
|
|
if( tool_manager == nullptr )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the selection to use to test if the action is enabled
|
|
|
|
SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection();
|
|
|
|
|
|
|
|
bool runAction = true;
|
|
|
|
|
|
|
|
if( const ACTION_CONDITIONS* aCond =
|
|
|
|
tool_manager->GetActionManager()->GetCondition( *context ) )
|
|
|
|
{
|
|
|
|
runAction = aCond->enableCondition( sel );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( runAction )
|
|
|
|
{
|
2023-06-26 22:16:51 +00:00
|
|
|
tool_manager->RunAction( *context );
|
2021-06-24 08:47:28 +00:00
|
|
|
m_canvas->Request_refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetSettingsChanged( long change )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetMotionFlag( bool value )
|
|
|
|
{
|
|
|
|
m_capIsMoving = value;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetTransaction( long value )
|
|
|
|
{
|
|
|
|
if( value != 0L )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_canvas->Request_refresh( true );
|
|
|
|
wxLogTrace( m_logTrace, wxT( "End of transaction" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position )
|
|
|
|
{
|
|
|
|
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const
|
|
|
|
{
|
|
|
|
matrix = { 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 };
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const
|
|
|
|
{
|
|
|
|
// Use the right-handed coordinate system X-right, Z-up, Y-in (row vectors)
|
2022-03-31 19:03:41 +00:00
|
|
|
matrix = { 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1 };
|
2021-06-24 08:47:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-05 08:04:36 +00:00
|
|
|
|
2021-06-24 08:47:28 +00:00
|
|
|
long NL_3D_VIEWER_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const
|
|
|
|
{
|
|
|
|
isRotatable = true;
|
|
|
|
return 0;
|
|
|
|
}
|