KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eda_3d_controller.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <3d_rendering/opengl/render_3d_opengl.h> // Must be included before any GL header
26
27#include <tool/actions.h>
28#include <tool/tool_manager.h>
29#include <eda_3d_canvas.h>
30#include <eda_3d_viewer_frame.h>
33#include <id.h>
34#include <kiface_base.h>
40
41
43{
44 std::shared_ptr<ACTION_MENU> rotateSubmenu = std::make_shared<ACTION_MENU>( true, this );
45 rotateSubmenu->SetUntranslatedTitle( _HKI( "Rotate Board" ) );
46 rotateSubmenu->SetIcon( BITMAPS::rotate_cw );
47 m_menu->RegisterSubMenu( rotateSubmenu );
48
49 rotateSubmenu->Add( EDA_3D_ACTIONS::rotateXCW );
50 rotateSubmenu->Add( EDA_3D_ACTIONS::rotateXCCW );
51 rotateSubmenu->AppendSeparator();
52 rotateSubmenu->Add( EDA_3D_ACTIONS::rotateYCW );
53 rotateSubmenu->Add( EDA_3D_ACTIONS::rotateYCCW );
54 rotateSubmenu->AppendSeparator();
55 rotateSubmenu->Add( EDA_3D_ACTIONS::rotateZCW );
56 rotateSubmenu->Add( EDA_3D_ACTIONS::rotateZCCW );
57
58 std::shared_ptr<ACTION_MENU> moveSubmenu = std::make_shared<ACTION_MENU>( true, this );
59 moveSubmenu->SetUntranslatedTitle( _HKI( "Move Board" ) );
60 moveSubmenu->SetIcon( BITMAPS::move );
61 m_menu->RegisterSubMenu( moveSubmenu );
62
63 moveSubmenu->Add( EDA_3D_ACTIONS::moveLeft );
64 moveSubmenu->Add( EDA_3D_ACTIONS::moveRight );
65 moveSubmenu->Add( EDA_3D_ACTIONS::moveUp );
66 moveSubmenu->Add( EDA_3D_ACTIONS::moveDown );
67
68 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
69
72
73 ctxMenu.AddSeparator();
80
81 ctxMenu.AddSeparator();
82 ctxMenu.AddMenu( rotateSubmenu.get(), SELECTION_CONDITIONS::ShowAlways );
84 ctxMenu.AddMenu( moveSubmenu.get(), SELECTION_CONDITIONS::ShowAlways );
85
86 return true;
87}
88
89
91{
92 m_canvas = nullptr;
93 m_boardAdapter = nullptr;
94 m_camera = nullptr;
95
96 TOOLS_HOLDER* holder = m_toolMgr->GetToolHolder();
97
98 wxCHECK( holder, /* void */ );
99 wxCHECK( holder->GetToolCanvas()->GetId() == EDA_3D_CANVAS_ID, /* void */ );
100
101 m_canvas = static_cast<EDA_3D_CANVAS*>( holder->GetToolCanvas() );
102
103 if( EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( holder ) )
104 {
105 wxCHECK( frame->GetFrameType() == FRAME_PCB_DISPLAY3D, /* void */ );
106
107 m_boardAdapter = &static_cast<EDA_3D_VIEWER_FRAME*>( frame )->GetAdapter();
108 m_camera = &static_cast<EDA_3D_VIEWER_FRAME*>( frame )->GetCurrentCamera();
109 }
110 else if( wxWindow* previewWindow = dynamic_cast<wxWindow*>( holder ) )
111 {
112 wxCHECK( previewWindow->GetId() == PANEL_PREVIEW_3D_MODEL_ID, /* void */ );
113
114 m_boardAdapter = &static_cast<PANEL_PREVIEW_3D_MODEL*>( holder )->GetAdapter();
115 m_camera = &static_cast<PANEL_PREVIEW_3D_MODEL*>( holder )->GetCurrentCamera();
116 }
117}
118
119
121{
122 ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
123 CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
124 SELECTION dummySel;
125
126 if( conditionalMenu )
127 conditionalMenu->Evaluate( dummySel );
128
129 if( actionMenu )
130 actionMenu->UpdateAll();
131
132 return 0;
133}
134
135
137{
138 // Main loop: keep receiving events
139 while( TOOL_EVENT* evt = Wait() )
140 {
141 if( evt->IsCancelInteractive() )
142 {
143 wxWindow* canvas = m_toolMgr->GetToolHolder()->GetToolCanvas();
144 KIWAY_HOLDER* parent = dynamic_cast<KIWAY_HOLDER*>( wxGetTopLevelParent( canvas ) );
145
146 if( parent && parent->GetType() == KIWAY_HOLDER::DIALOG )
147 {
148 DIALOG_SHIM* dialog = static_cast<DIALOG_SHIM*>( parent );
149
150 if( dialog->IsQuasiModal() )
151 dialog->EndQuasiModal( wxID_CANCEL );
152 else
153 dialog->EndModal( wxID_CANCEL );
154 }
155 else
156 {
157 evt->SetPassEvent();
158 }
159 }
160 else if( evt->IsMouseDown() )
161 {
162 }
163 else if( evt->IsClick() && ( evt->Buttons() & BUT_RIGHT ) )
164 {
165
166 if( !m_canvas->m_mouse_was_moved )
167 m_menu->ShowContextMenu();
168 }
169 else
170 {
171 evt->SetPassEvent();
172 }
173 }
174
175 return 0;
176}
177
178
180{
181 m_canvas->SetView3D( aEvent.Parameter<VIEW3D_TYPE>() );
182
183 return 0;
184}
185
186
188{
189 switch( aEvent.Parameter<ACTIONS::CURSOR_EVENT_TYPE>() )
190 {
191 case ACTIONS::CURSOR_UP: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_UP ); break;
195 default: wxFAIL; break;
196 }
197
198 return 0;
199}
200
201
203{
204 double rotIncrement = glm::radians( m_rotationIncrement );
205
206 switch( aEvent.Parameter<ROTATION_DIR>() )
207 {
208 case ROTATION_DIR::X_CW: m_camera->RotateX( -rotIncrement ); break;
209 case ROTATION_DIR::X_CCW: m_camera->RotateX( rotIncrement ); break;
210
212 case ROTATION_DIR::Y_CW: m_camera->RotateY( rotIncrement ); break;
213 case ROTATION_DIR::Y_CCW: m_camera->RotateY( -rotIncrement ); break;
214 case ROTATION_DIR::Z_CW: m_camera->RotateZ( -rotIncrement ); break;
215 case ROTATION_DIR::Z_CCW: m_camera->RotateZ( rotIncrement ); break;
216 default: wxFAIL; break;
217 }
218
219 if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
220 m_canvas->Request_refresh();
221 else
222 m_canvas->RenderRaytracingRequest();
223
224 return 0;
225}
226
227
229{
230 m_boardAdapter->m_Cfg->m_Render.material_mode = aEvent.Parameter<MATERIAL_MODE>();
231
232 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
233
234 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
235 static_cast<EDA_3D_VIEWER_FRAME*>( frame )->NewDisplay( true );
236 else
237 m_canvas->Request_refresh();
238
239 return 0;
240}
241
242
244{
245 m_camera->ToggleProjection();
246
247 if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
248 m_canvas->Request_refresh();
249 else
250 m_canvas->RenderRaytracingRequest();
251
252 return 0;
253}
254
256{
257 std::bitset<LAYER_3D_END> visibilityFlags = m_boardAdapter->GetVisibleLayers();
258 APPEARANCE_CONTROLS_3D* appearanceManager = nullptr;
259
260 auto flipLayer =
261 [&]( int layer )
262 {
263 appearanceManager->OnLayerVisibilityChanged( layer, !visibilityFlags.test( layer ) );
264 };
265
266 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
267
268 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
269 appearanceManager = static_cast<EDA_3D_VIEWER_FRAME*>( frame )->GetAppearanceManager();
270
271 if( appearanceManager )
272 {
273 if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) ) flipLayer( LAYER_3D_TH_MODELS );
274 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) ) flipLayer( LAYER_3D_SMD_MODELS );
275 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) ) flipLayer( LAYER_3D_VIRTUAL_MODELS );
277 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) ) flipLayer( LAYER_3D_MODELS_MARKED_DNP );
278 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNavigator ) ) flipLayer( LAYER_3D_NAVIGATOR );
279 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) ) flipLayer( LAYER_3D_BOUNDING_BOXES );
280 }
281
282 return 0;
283}
284
285
287{
288 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
289
290 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
291 static_cast<EDA_3D_VIEWER_FRAME*>( frame )->ToggleAppearanceManager();
292
293 return 0;
294}
295
296
298{
299 m_boardAdapter->m_Cfg->m_Render.grid_type = aEvent.Parameter<GRID3D_TYPE>();
300
301 if( m_canvas )
302 m_canvas->Request_refresh();
303
304 return 0;
305}
306
307
309{
310 m_canvas->Request_refresh();
311 return 0;
312}
313
314
316{
317 bool direction = aEvent.IsAction( &ACTIONS::zoomIn );
318 return doZoomInOut( direction, true );
319}
320
321
323{
324 bool direction = aEvent.IsAction( &ACTIONS::zoomInCenter );
325 return doZoomInOut( direction, false );
326}
327
328
329int EDA_3D_CONTROLLER::doZoomInOut( bool aDirection, bool aCenterOnCursor )
330{
331 if( m_canvas )
332 {
334 m_canvas->DisplayStatus();
335 }
336
337 return 0;
338}
339
340
342{
343 if( m_canvas )
344 {
346 m_canvas->DisplayStatus();
347 }
348
349 return 0;
350}
351
352
354{
355 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
356
357 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
358 static_cast<EDA_3D_VIEWER_FRAME*>( frame )->NewDisplay( true );
359
360 return 0;
361}
362
363
365{
366 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
367
368 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
369 {
370 EDA_3D_VIEWER_FRAME* frame3d = static_cast<EDA_3D_VIEWER_FRAME*>( frame );
371
372 RENDER_ENGINE& engine = frame3d->GetAdapter().m_Cfg->m_Render.engine;
373 RENDER_ENGINE old_engine = engine;
374
375 if( old_engine == RENDER_ENGINE::OPENGL )
377 else
378 engine = RENDER_ENGINE::OPENGL;
379
380 // Directly tell the canvas the rendering engine changed
381 if( old_engine != engine )
382 frame3d->GetCanvas()->RenderEngineChanged();
383 }
384
385 return 0;
386}
387
388
390{
391 m_boardAdapter->m_Cfg->m_Render.show_missing_models = !m_boardAdapter->m_Cfg->m_Render.show_missing_models;
392 m_canvas->ReloadRequest();
393 m_canvas->Request_refresh();
394 return 0;
395}
396
397
399{
400 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
401
402 if( !frame || frame->GetFrameType() != FRAME_PCB_DISPLAY3D )
403 return 0;
404
405 EDA_3D_VIEWER_FRAME* viewer = static_cast<EDA_3D_VIEWER_FRAME*>( frame );
407
408 wxSize currentSize = viewer->GetCanvas()->GetClientSize();
409
411 {
412 viewer->ExportImage( fmt, currentSize );
413 return 0;
414 }
415
417 DIALOG_EXPORT_3D_IMAGE dlg( viewer, currentSize, cfg ? &cfg->m_ExportImage : nullptr );
418
419 if( dlg.ShowModal() == wxID_OK )
420 viewer->ExportImage( fmt, dlg.GetSize() );
421
422 return 0;
423}
424
425
427{
430
431 // Miscellaneous control
437
438 // Pan control
447
448 // View rotation
464
465 // Zoom control
470 // zoom in/out at cursor does not exist in 3D viewer but because F1 and F2 keys generate
471 // a zoomIn/zoomOut event, these events must be captured to use these hot keys. The actual
472 // zoom is the same as ZoomInOutCenter
475
476 // Grid
482
483 // Material
487
488 // Visibility
497}
498
499
ROTATION_DIR
Rotation direction for the 3d canvas.
Definition 3d_enums.h:35
GRID3D_TYPE
Grid types.
Definition 3d_enums.h:54
MATERIAL_MODE
Render 3d model shape materials mode.
Definition 3d_enums.h:71
RENDER_ENGINE
Render engine mode.
Definition 3d_enums.h:64
VIEW3D_TYPE
Definition 3d_enums.h:78
@ VIEW3D_ZOOM_OUT
Definition 3d_enums.h:94
@ VIEW3D_PAN_LEFT
Definition 3d_enums.h:91
@ VIEW3D_FIT_SCREEN
Definition 3d_enums.h:98
@ VIEW3D_ZOOM_IN
Definition 3d_enums.h:93
@ VIEW3D_PAN_UP
Definition 3d_enums.h:89
@ VIEW3D_PAN_DOWN
Definition 3d_enums.h:90
@ VIEW3D_PAN_RIGHT
Definition 3d_enums.h:92
static TOOL_ACTION zoomRedraw
Definition actions.h:132
static TOOL_ACTION zoomOutCenter
Definition actions.h:136
static TOOL_ACTION zoomIn
Definition actions.h:133
static TOOL_ACTION zoomOut
Definition actions.h:134
static TOOL_ACTION panDown
Definition actions.h:185
CURSOR_EVENT_TYPE
Definition actions.h:303
@ CURSOR_RIGHT
Definition actions.h:311
@ CURSOR_LEFT
Definition actions.h:309
@ CURSOR_UP
Definition actions.h:305
@ CURSOR_DOWN
Definition actions.h:307
static TOOL_ACTION panLeft
Definition actions.h:186
static TOOL_ACTION updateMenu
Definition actions.h:270
static TOOL_ACTION zoomFitScreen
Definition actions.h:142
static TOOL_ACTION panUp
Definition actions.h:184
static TOOL_ACTION zoomInCenter
Definition actions.h:135
static TOOL_ACTION panRight
Definition actions.h:187
Define the structure of a menu based on ACTIONs.
Definition action_menu.h:47
void UpdateAll()
Run update handlers for the menu and its submenus.
void OnLayerVisibilityChanged(int aLayer, bool isVisible)
EDA_3D_VIEWER_SETTINGS * m_Cfg
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:69
bool IsQuasiModal() const
Definition dialog_shim.h:94
void EndQuasiModal(int retCode)
int ShowModal() override
static TOOL_ACTION showNavigator
static TOOL_ACTION showLayersManager
static TOOL_ACTION rotateXCCW
static TOOL_ACTION showNotInPosFile
static TOOL_ACTION exportImage
static TOOL_ACTION showTHT
static TOOL_ACTION noGrid
static TOOL_ACTION show2_5mmGrid
static TOOL_ACTION reloadBoard
static TOOL_ACTION rotateZCCW
static TOOL_ACTION rotateZCW
static TOOL_ACTION rotateYCCW
static TOOL_ACTION rotateXCW
static TOOL_ACTION viewTop
static TOOL_ACTION show1mmGrid
static TOOL_ACTION showDNP
static TOOL_ACTION toggleOrtho
static TOOL_ACTION moveLeft
static TOOL_ACTION toggleShowMissingModels
static TOOL_ACTION viewLeft
static TOOL_ACTION show10mmGrid
static TOOL_ACTION toggleRaytacing
static TOOL_ACTION viewBack
static TOOL_ACTION show5mmGrid
static TOOL_ACTION viewRight
static TOOL_ACTION showSMD
static TOOL_ACTION homeView
static TOOL_ACTION moveUp
static TOOL_ACTION flipView
static TOOL_ACTION moveDown
static TOOL_ACTION viewBottom
static TOOL_ACTION copyToClipboard
static TOOL_ACTION moveRight
static TOOL_ACTION materialDiffuse
static TOOL_ACTION pivotCenter
static TOOL_ACTION controlActivate
static TOOL_ACTION showVirtual
static TOOL_ACTION rotateYCW
static TOOL_ACTION materialCAD
static TOOL_ACTION viewFront
static TOOL_ACTION showBBoxes
static TOOL_ACTION materialNormal
Implement a canvas based on a wxGLCanvas.
void RenderEngineChanged()
Notify that the render engine was changed.
int On3DGridSelection(const TOOL_EVENT &aEvent)
double m_rotationIncrement
Rotation increment for the rotate actions (degrees)
int ZoomFitScreen(const TOOL_EVENT &aEvent)
EDA_3D_CANVAS * m_canvas
int ExportImage(const TOOL_EVENT &aEvent)
int doZoomInOut(bool aDirection, bool aCenterOnCursor)
int ToggleLayersManager(const TOOL_EVENT &aEvent)
int ToggleRaytracing(const TOOL_EVENT &aEvent)
int Main(const TOOL_EVENT &aEvent)
BOARD_ADAPTER * m_boardAdapter
int ZoomRedraw(const TOOL_EVENT &aEvent)
int ToggleOrtho(const TOOL_EVENT &aEvent)
int PanControl(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
int ToggleVisibility(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
void setTransitions() override
Set up handlers for various events.
int RotateView(const TOOL_EVENT &aEvent)
int ToggleShowMissingModels(const TOOL_EVENT &aEvent)
int SetMaterial(const TOOL_EVENT &aEvent)
int UpdateMenu(const TOOL_EVENT &aEvent)
int ViewControl(const TOOL_EVENT &aEvent)
int ReloadBoard(const TOOL_EVENT &aEvent)
int ZoomInOutCenter(const TOOL_EVENT &aEvent)
int ZoomInOut(const TOOL_EVENT &aEvent)
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
EDA_3D_CANVAS * GetCanvas()
BOARD_ADAPTER & GetAdapter()
void ExportImage(EDA_3D_VIEWER_EXPORT_FORMAT aFormat, const wxSize &aSize)
Export 3D viewer image to file or clipboard.
EXPORT_IMAGE_SETTINGS m_ExportImage
The base frame for deriving all KiCad main window classes.
FRAME_T GetFrameType() const
A mix in class which holds the location of a wxWindow's KIWAY.
HOLDER_TYPE GetType() const
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:224
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:78
Generic, UI-independent tool event.
Definition tool_event.h:171
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
std::unique_ptr< TOOL_MENU > m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
#define EDA_3D_CANVAS_ID
Declaration of the eda_3d_viewer class.
EDA_3D_VIEWER_EXPORT_FORMAT
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:47
@ LAYER_3D_NAVIGATOR
Definition layer_ids.h:619
@ LAYER_3D_BOUNDING_BOXES
Definition layer_ids.h:620
@ LAYER_3D_SMD_MODELS
Definition layer_ids.h:615
@ LAYER_3D_TH_MODELS
Definition layer_ids.h:614
@ LAYER_3D_VIRTUAL_MODELS
Definition layer_ids.h:616
@ LAYER_3D_MODELS_MARKED_DNP
Definition layer_ids.h:618
@ LAYER_3D_MODELS_NOT_IN_POS
Definition layer_ids.h:617
#define _HKI(x)
Definition page_info.cpp:44
#define PANEL_PREVIEW_3D_MODEL_ID
T * GetAppSettings(const char *aFilename)
@ BUT_RIGHT
Definition tool_event.h:133