7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2024-11-22 16:05:01 +00:00
kicad/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp
Tomasz Wlostowski 9963b9dd9f TOOL_INTERACTIVE: only create the context menu when we are running in GUI mode
TOOL_MENU::m_menu was unconditionally created by the TOOL_INTERACTIVE constructor, resulting in crashes if
we wanted to run the TOOLs in headless  mode, e.g. in unit tests. This commits makes
the creation of the menu object dependent on Pgm::IsGui().
2024-08-13 22:50:26 +02:00

388 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();
if( DIALOG_SHIM* dialog = dynamic_cast<DIALOG_SHIM*>( wxGetTopLevelParent( canvas ) ) )
{
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::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() );
}