392 lines
14 KiB
C++
392 lines
14 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2023 CERN
|
|
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* 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/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <tool/actions.h>
|
|
#include <tool/tool_manager.h>
|
|
#include <eda_3d_canvas.h>
|
|
#include <eda_3d_viewer_frame.h>
|
|
#include <id.h>
|
|
#include <kiface_base.h>
|
|
#include <tools/eda_3d_controller.h>
|
|
#include <tools/eda_3d_actions.h>
|
|
#include <dialogs/panel_preview_3d_model.h>
|
|
#include <dialogs/appearance_controls_3D.h>
|
|
#include <3d_rendering/opengl/render_3d_opengl.h>
|
|
|
|
|
|
bool EDA_3D_CONTROLLER::Init()
|
|
{
|
|
CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
|
|
|
|
ctxMenu.AddItem( ACTIONS::zoomInCenter, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( ACTIONS::zoomOutCenter, SELECTION_CONDITIONS::ShowAlways );
|
|
|
|
ctxMenu.AddSeparator();
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewTop, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewBottom, SELECTION_CONDITIONS::ShowAlways );
|
|
|
|
ctxMenu.AddSeparator();
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewRight, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewLeft, SELECTION_CONDITIONS::ShowAlways );
|
|
|
|
ctxMenu.AddSeparator();
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewFront, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewBack, SELECTION_CONDITIONS::ShowAlways );
|
|
|
|
ctxMenu.AddSeparator();
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::flipView, SELECTION_CONDITIONS::ShowAlways );
|
|
|
|
ctxMenu.AddSeparator();
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::moveLeft, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::moveRight, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::moveUp, SELECTION_CONDITIONS::ShowAlways );
|
|
ctxMenu.AddItem( EDA_3D_ACTIONS::moveDown, SELECTION_CONDITIONS::ShowAlways );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void EDA_3D_CONTROLLER::Reset( RESET_REASON aReason )
|
|
{
|
|
TOOLS_HOLDER* holder = m_toolMgr->GetToolHolder();
|
|
|
|
wxASSERT( holder );
|
|
|
|
m_canvas = nullptr;
|
|
m_boardAdapter = nullptr;
|
|
m_camera = nullptr;
|
|
|
|
if( holder )
|
|
{
|
|
m_canvas = dynamic_cast<EDA_3D_CANVAS*>( holder->GetToolCanvas() );
|
|
|
|
EDA_3D_BOARD_HOLDER* holder3d = dynamic_cast<EDA_3D_BOARD_HOLDER*>( holder );
|
|
|
|
wxASSERT( holder3d );
|
|
|
|
if( holder3d )
|
|
{
|
|
m_boardAdapter = &holder3d->GetAdapter();
|
|
m_camera = &holder3d->GetCurrentCamera();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::UpdateMenu( const TOOL_EVENT& aEvent )
|
|
{
|
|
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
|
|
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
|
|
SELECTION dummySel;
|
|
|
|
if( conditionalMenu )
|
|
conditionalMenu->Evaluate( dummySel );
|
|
|
|
if( actionMenu )
|
|
actionMenu->UpdateAll();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::Main( const TOOL_EVENT& aEvent )
|
|
{
|
|
// Main loop: keep receiving events
|
|
while( TOOL_EVENT* evt = Wait() )
|
|
{
|
|
if( evt->IsCancelInteractive() )
|
|
{
|
|
wxWindow* canvas = m_toolMgr->GetToolHolder()->GetToolCanvas();
|
|
wxWindow* topLevelParent = wxGetTopLevelParent( canvas->GetParent() );
|
|
|
|
if( topLevelParent && dynamic_cast<DIALOG_SHIM*>( topLevelParent ) )
|
|
{
|
|
DIALOG_SHIM* dialog = static_cast<DIALOG_SHIM*>( topLevelParent );
|
|
|
|
if( dialog->IsQuasiModal() )
|
|
dialog->EndQuasiModal( wxID_CANCEL );
|
|
else
|
|
dialog->EndModal( wxID_CANCEL );
|
|
}
|
|
else
|
|
{
|
|
evt->SetPassEvent();
|
|
}
|
|
}
|
|
else if( evt->IsClick( BUT_RIGHT ) )
|
|
{
|
|
m_menu.ShowContextMenu();
|
|
}
|
|
else
|
|
{
|
|
evt->SetPassEvent();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ViewControl( const TOOL_EVENT& aEvent )
|
|
{
|
|
m_canvas->SetView3D( aEvent.Parameter<VIEW3D_TYPE>() );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::PanControl( const TOOL_EVENT& aEvent )
|
|
{
|
|
switch( aEvent.Parameter<ACTIONS::CURSOR_EVENT_TYPE>() )
|
|
{
|
|
case ACTIONS::CURSOR_UP: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_UP ); break;
|
|
case ACTIONS::CURSOR_DOWN: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_DOWN ); break;
|
|
case ACTIONS::CURSOR_LEFT: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_LEFT ); break;
|
|
case ACTIONS::CURSOR_RIGHT: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_RIGHT ); break;
|
|
default: wxFAIL; break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::RotateView( const TOOL_EVENT& aEvent )
|
|
{
|
|
double rotIncrement = glm::radians( m_rotationIncrement );
|
|
|
|
switch( aEvent.Parameter<ROTATION_DIR>() )
|
|
{
|
|
case ROTATION_DIR::X_CW: m_camera->RotateX( -rotIncrement ); break;
|
|
case ROTATION_DIR::X_CCW: m_camera->RotateX( rotIncrement ); break;
|
|
/// Y rotations are backward b/c the RHR has Y pointing into the screen
|
|
case ROTATION_DIR::Y_CW: m_camera->RotateY( rotIncrement ); break;
|
|
case ROTATION_DIR::Y_CCW: m_camera->RotateY( -rotIncrement ); break;
|
|
case ROTATION_DIR::Z_CW: m_camera->RotateZ( -rotIncrement ); break;
|
|
case ROTATION_DIR::Z_CCW: m_camera->RotateZ( rotIncrement ); break;
|
|
default: wxFAIL; break;
|
|
}
|
|
|
|
if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
|
|
m_canvas->Request_refresh();
|
|
else
|
|
m_canvas->RenderRaytracingRequest();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::SetMaterial( const TOOL_EVENT& aEvent )
|
|
{
|
|
m_boardAdapter->m_Cfg->m_Render.material_mode = aEvent.Parameter<MATERIAL_MODE>();
|
|
|
|
if( auto* viewer = dynamic_cast<EDA_3D_VIEWER_FRAME*>( m_toolMgr->GetToolHolder() ) )
|
|
viewer->NewDisplay( true );
|
|
else
|
|
m_canvas->Request_refresh();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ToggleOrtho( const TOOL_EVENT& aEvent )
|
|
{
|
|
m_camera->ToggleProjection();
|
|
|
|
if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
|
|
m_canvas->Request_refresh();
|
|
else
|
|
m_canvas->RenderRaytracingRequest();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int EDA_3D_CONTROLLER::ToggleVisibility( const TOOL_EVENT& aEvent )
|
|
{
|
|
std::bitset<LAYER_3D_END> visibilityFlags = m_boardAdapter->GetVisibleLayers();
|
|
APPEARANCE_CONTROLS_3D* appearanceManager = nullptr;
|
|
|
|
auto flipLayer =
|
|
[&]( int layer )
|
|
{
|
|
appearanceManager->OnLayerVisibilityChanged( layer, !visibilityFlags.test( layer ) );
|
|
};
|
|
|
|
if( auto viewer = dynamic_cast<EDA_3D_VIEWER_FRAME*>( m_toolMgr->GetToolHolder() ) )
|
|
appearanceManager = viewer->GetAppearanceManager();
|
|
|
|
if( appearanceManager )
|
|
{
|
|
if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) )
|
|
flipLayer( LAYER_3D_TH_MODELS );
|
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) )
|
|
flipLayer( LAYER_3D_SMD_MODELS );
|
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) )
|
|
flipLayer( LAYER_3D_VIRTUAL_MODELS );
|
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNotInPosFile ) )
|
|
flipLayer( LAYER_3D_MODELS_NOT_IN_POS );
|
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) )
|
|
flipLayer( LAYER_3D_MODELS_MARKED_DNP );
|
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showAxis ) )
|
|
flipLayer( LAYER_3D_AXES );
|
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) )
|
|
flipLayer( LAYER_3D_BOUNDING_BOXES );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ToggleLayersManager( const TOOL_EVENT& aEvent )
|
|
{
|
|
if( auto* viewer = dynamic_cast<EDA_3D_VIEWER_FRAME*>( m_toolMgr->GetToolHolder() ) )
|
|
viewer->ToggleAppearanceManager();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::On3DGridSelection( const TOOL_EVENT& aEvent )
|
|
{
|
|
m_boardAdapter->m_Cfg->m_Render.grid_type = aEvent.Parameter<GRID3D_TYPE>();
|
|
|
|
if( m_canvas )
|
|
m_canvas->Request_refresh();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ZoomRedraw( const TOOL_EVENT& aEvent )
|
|
{
|
|
m_canvas->Request_refresh();
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ZoomInOut( const TOOL_EVENT& aEvent )
|
|
{
|
|
bool direction = aEvent.IsAction( &ACTIONS::zoomIn );
|
|
return doZoomInOut( direction, true );
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ZoomInOutCenter( const TOOL_EVENT& aEvent )
|
|
{
|
|
bool direction = aEvent.IsAction( &ACTIONS::zoomInCenter );
|
|
return doZoomInOut( direction, false );
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::doZoomInOut( bool aDirection, bool aCenterOnCursor )
|
|
{
|
|
if( m_canvas )
|
|
{
|
|
m_canvas->SetView3D( aDirection ? VIEW3D_TYPE::VIEW3D_ZOOM_IN : VIEW3D_TYPE::VIEW3D_ZOOM_OUT );
|
|
m_canvas->DisplayStatus();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int EDA_3D_CONTROLLER::ZoomFitScreen( const TOOL_EVENT& aEvent )
|
|
{
|
|
if( m_canvas )
|
|
{
|
|
m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_FIT_SCREEN );
|
|
m_canvas->DisplayStatus();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void EDA_3D_CONTROLLER::setTransitions()
|
|
{
|
|
Go( &EDA_3D_CONTROLLER::Main, EDA_3D_ACTIONS::controlActivate.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );
|
|
|
|
// Pan control
|
|
Go( &EDA_3D_CONTROLLER::PanControl, ACTIONS::panUp.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, ACTIONS::panDown.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, ACTIONS::panLeft.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, ACTIONS::panRight.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, EDA_3D_ACTIONS::moveUp.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, EDA_3D_ACTIONS::moveDown.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, EDA_3D_ACTIONS::moveLeft.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::PanControl, EDA_3D_ACTIONS::moveRight.MakeEvent() );
|
|
|
|
// View rotation
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::viewTop.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::viewBottom.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::viewLeft.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::viewRight.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::viewFront.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::viewBack.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::pivotCenter.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::homeView.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::resetView.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ViewControl, EDA_3D_ACTIONS::flipView.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::RotateView, EDA_3D_ACTIONS::rotateXCW.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::RotateView, EDA_3D_ACTIONS::rotateXCCW.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::RotateView, EDA_3D_ACTIONS::rotateYCW.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::RotateView, EDA_3D_ACTIONS::rotateYCCW.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::RotateView, EDA_3D_ACTIONS::rotateZCW.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::RotateView, EDA_3D_ACTIONS::rotateZCCW.MakeEvent() );
|
|
|
|
// Zoom control
|
|
Go( &EDA_3D_CONTROLLER::ZoomRedraw, ACTIONS::zoomRedraw.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ZoomInOutCenter, ACTIONS::zoomInCenter.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ZoomInOutCenter, ACTIONS::zoomOutCenter.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ZoomFitScreen, ACTIONS::zoomFitScreen.MakeEvent() );
|
|
// zoom in/out at cursor does not exist in 3D viewer but because F1 and F2 keys generate
|
|
// a zoomIn/zoomOut event, these events must be captured to use these hot keys. The actual
|
|
// zoom is the same as ZoomInOutCenter
|
|
Go( &EDA_3D_CONTROLLER::ZoomInOut, ACTIONS::zoomIn.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ZoomInOut, ACTIONS::zoomOut.MakeEvent() );
|
|
|
|
// Grid
|
|
Go( &EDA_3D_CONTROLLER::On3DGridSelection, EDA_3D_ACTIONS::noGrid.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::On3DGridSelection, EDA_3D_ACTIONS::show10mmGrid.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::On3DGridSelection, EDA_3D_ACTIONS::show5mmGrid.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::On3DGridSelection, EDA_3D_ACTIONS::show2_5mmGrid.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::On3DGridSelection, EDA_3D_ACTIONS::show1mmGrid.MakeEvent() );
|
|
|
|
// Material
|
|
Go( &EDA_3D_CONTROLLER::SetMaterial, EDA_3D_ACTIONS::materialNormal.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::SetMaterial, EDA_3D_ACTIONS::materialDiffuse.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::SetMaterial, EDA_3D_ACTIONS::materialCAD.MakeEvent() );
|
|
|
|
// Visibility
|
|
Go( &EDA_3D_CONTROLLER::ToggleOrtho, EDA_3D_ACTIONS::toggleOrtho.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showTHT.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showSMD.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showVirtual.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showNotInPosFile.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showDNP.MakeEvent() );
|
|
Go( &EDA_3D_CONTROLLER::ToggleLayersManager,EDA_3D_ACTIONS::showLayersManager.MakeEvent() );
|
|
}
|
|
|
|
|