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 <tool/actions.h>
26#include <tool/tool_manager.h>
27#include <eda_3d_canvas.h>
28#include <eda_3d_viewer_frame.h>
29#include <id.h>
30#include <kiface_base.h>
37
38
40{
41 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
42
45
46 ctxMenu.AddSeparator();
49
50 ctxMenu.AddSeparator();
53
54 ctxMenu.AddSeparator();
57
58 ctxMenu.AddSeparator();
60
61 ctxMenu.AddSeparator();
66
67 return true;
68}
69
70
72{
73 m_canvas = nullptr;
74 m_boardAdapter = nullptr;
75 m_camera = nullptr;
76
78
79 wxCHECK( holder, /* void */ );
80 wxCHECK( holder->GetToolCanvas()->GetId() == EDA_3D_CANVAS_ID, /* void */ );
81
82 m_canvas = static_cast<EDA_3D_CANVAS*>( holder->GetToolCanvas() );
83
84 if( EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( holder ) )
85 {
86 wxCHECK( frame->GetFrameType() == FRAME_PCB_DISPLAY3D, /* void */ );
87
88 m_boardAdapter = &static_cast<EDA_3D_VIEWER_FRAME*>( frame )->GetAdapter();
89 m_camera = &static_cast<EDA_3D_VIEWER_FRAME*>( frame )->GetCurrentCamera();
90 }
91 else if( wxWindow* previewWindow = dynamic_cast<wxWindow*>( holder ) )
92 {
93 wxCHECK( previewWindow->GetId() == PANEL_PREVIEW_3D_MODEL_ID, /* void */ );
94
95 m_boardAdapter = &static_cast<PANEL_PREVIEW_3D_MODEL*>( holder )->GetAdapter();
96 m_camera = &static_cast<PANEL_PREVIEW_3D_MODEL*>( holder )->GetCurrentCamera();
97 }
98}
99
100
102{
103 ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
104 CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
105 SELECTION dummySel;
106
107 if( conditionalMenu )
108 conditionalMenu->Evaluate( dummySel );
109
110 if( actionMenu )
111 actionMenu->UpdateAll();
112
113 return 0;
114}
115
116
118{
119 // Track right mouse button state and movement
120 VECTOR2D rightButtonDownPos;
121
122 const int DRAG_THRESHOLD = 4; // pixels
123 bool rightButtonDragged = false;
124
125 // Main loop: keep receiving events
126 while( TOOL_EVENT* evt = Wait() )
127 {
128 if( evt->IsCancelInteractive() )
129 {
130 wxWindow* canvas = m_toolMgr->GetToolHolder()->GetToolCanvas();
131 KIWAY_HOLDER* parent = dynamic_cast<KIWAY_HOLDER*>( wxGetTopLevelParent( canvas ) );
132
133 if( parent && parent->GetType() == KIWAY_HOLDER::DIALOG )
134 {
135 DIALOG_SHIM* dialog = static_cast<DIALOG_SHIM*>( parent );
136
137 if( dialog->IsQuasiModal() )
138 dialog->EndQuasiModal( wxID_CANCEL );
139 else
140 dialog->EndModal( wxID_CANCEL );
141 }
142 else
143 {
144 evt->SetPassEvent();
145 }
146 }
147 else if( evt->IsMouseDown() )
148 {
149 }
150 else if( evt->IsClick() && ( evt->Buttons() & BUT_RIGHT ) )
151 {
152
154 m_menu->ShowContextMenu();
155 }
156 else
157 {
158 evt->SetPassEvent();
159 }
160 }
161
162 return 0;
163}
164
165
167{
169
170 return 0;
171}
172
173
175{
176 switch( aEvent.Parameter<ACTIONS::CURSOR_EVENT_TYPE>() )
177 {
178 case ACTIONS::CURSOR_UP: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_UP ); break;
179 case ACTIONS::CURSOR_DOWN: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_DOWN ); break;
180 case ACTIONS::CURSOR_LEFT: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_LEFT ); break;
181 case ACTIONS::CURSOR_RIGHT: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_RIGHT ); break;
182 default: wxFAIL; break;
183 }
184
185 return 0;
186}
187
188
190{
191 double rotIncrement = glm::radians( m_rotationIncrement );
192
193 switch( aEvent.Parameter<ROTATION_DIR>() )
194 {
195 case ROTATION_DIR::X_CW: m_camera->RotateX( -rotIncrement ); break;
196 case ROTATION_DIR::X_CCW: m_camera->RotateX( rotIncrement ); break;
197
199 case ROTATION_DIR::Y_CW: m_camera->RotateY( rotIncrement ); break;
200 case ROTATION_DIR::Y_CCW: m_camera->RotateY( -rotIncrement ); break;
201 case ROTATION_DIR::Z_CW: m_camera->RotateZ( -rotIncrement ); break;
202 case ROTATION_DIR::Z_CCW: m_camera->RotateZ( rotIncrement ); break;
203 default: wxFAIL; break;
204 }
205
206 if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
208 else
210
211 return 0;
212}
213
214
216{
218
219 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
220
221 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
222 static_cast<EDA_3D_VIEWER_FRAME*>( frame )->NewDisplay( true );
223 else
225
226 return 0;
227}
228
229
231{
233
234 if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
236 else
238
239 return 0;
240}
241
243{
244 std::bitset<LAYER_3D_END> visibilityFlags = m_boardAdapter->GetVisibleLayers();
245 APPEARANCE_CONTROLS_3D* appearanceManager = nullptr;
246
247 auto flipLayer =
248 [&]( int layer )
249 {
250 appearanceManager->OnLayerVisibilityChanged( layer,
251 !visibilityFlags.test( layer ) );
252 };
253
254 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
255
256 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
257 appearanceManager = static_cast<EDA_3D_VIEWER_FRAME*>( frame )->GetAppearanceManager();
258
259 if( appearanceManager )
260 {
261 if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) )
262 flipLayer( LAYER_3D_TH_MODELS );
263 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) )
264 flipLayer( LAYER_3D_SMD_MODELS );
265 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) )
266 flipLayer( LAYER_3D_VIRTUAL_MODELS );
267 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNotInPosFile ) )
268 flipLayer( LAYER_3D_MODELS_NOT_IN_POS );
269 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) )
270 flipLayer( LAYER_3D_MODELS_MARKED_DNP );
271 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNavigator ) )
272 flipLayer( LAYER_3D_NAVIGATOR );
273 else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) )
274 flipLayer( LAYER_3D_BOUNDING_BOXES );
275 }
276
277 return 0;
278}
279
280
282{
283 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
284
285 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
286 static_cast<EDA_3D_VIEWER_FRAME*>( frame )->ToggleAppearanceManager();
287
288 return 0;
289}
290
291
293{
295
296 if( m_canvas )
298
299 return 0;
300}
301
302
304{
306 return 0;
307}
308
309
311{
312 bool direction = aEvent.IsAction( &ACTIONS::zoomIn );
313 return doZoomInOut( direction, true );
314}
315
316
318{
319 bool direction = aEvent.IsAction( &ACTIONS::zoomInCenter );
320 return doZoomInOut( direction, false );
321}
322
323
324int EDA_3D_CONTROLLER::doZoomInOut( bool aDirection, bool aCenterOnCursor )
325{
326 if( m_canvas )
327 {
328 m_canvas->SetView3D( aDirection ? VIEW3D_TYPE::VIEW3D_ZOOM_IN
329 : VIEW3D_TYPE::VIEW3D_ZOOM_OUT );
331 }
332
333 return 0;
334}
335
336
338{
339 if( m_canvas )
340 {
341 m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_FIT_SCREEN );
343 }
344
345 return 0;
346}
347
348
350{
351 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
352
353 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
354 static_cast<EDA_3D_VIEWER_FRAME*>( frame )->NewDisplay( true );
355
356 return 0;
357}
358
359
361{
362 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
363
364 if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
365 {
366 EDA_3D_VIEWER_FRAME* frame3d = static_cast<EDA_3D_VIEWER_FRAME*>( frame );
367
368 RENDER_ENGINE& engine = frame3d->GetAdapter().m_Cfg->m_Render.engine;
369 RENDER_ENGINE old_engine = engine;
370
371 if( old_engine == RENDER_ENGINE::OPENGL )
372 engine = RENDER_ENGINE::RAYTRACING;
373 else
374 engine = RENDER_ENGINE::OPENGL;
375
376 // Directly tell the canvas the rendering engine changed
377 if( old_engine != engine )
378 frame3d->GetCanvas()->RenderEngineChanged();
379 }
380
381 return 0;
382}
383
384
386{
387 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
388
389 if( !frame || frame->GetFrameType() != FRAME_PCB_DISPLAY3D )
390 return 0;
391
392 EDA_3D_VIEWER_FRAME* viewer = static_cast<EDA_3D_VIEWER_FRAME*>( frame );
394
395 wxSize currentSize = viewer->GetCanvas()->GetClientSize();
396
397 if( fmt == EDA_3D_VIEWER_EXPORT_FORMAT::CLIPBOARD )
398 {
399 viewer->ExportImage( fmt, currentSize );
400 return 0;
401 }
402
403 static wxSize lastSize( viewer->GetCanvas()->GetClientSize() );
404 static EDA_3D_VIEWER_EXPORT_FORMAT lastFormat = EDA_3D_VIEWER_EXPORT_FORMAT::PNG;
405 DIALOG_EXPORT_3D_IMAGE dlg( viewer, currentSize );
406
407 if( dlg.ShowModal() == wxID_OK )
408 viewer->ExportImage( lastFormat, dlg.GetSize() );
409
410 return 0;
411}
412
413
415{
418
419 // Miscellaneous control
424
425 // Pan control
434
435 // View rotation
451
452 // Zoom control
457 // zoom in/out at cursor does not exist in 3D viewer but because F1 and F2 keys generate
458 // a zoomIn/zoomOut event, these events must be captured to use these hot keys. The actual
459 // zoom is the same as ZoomInOutCenter
462
463 // Grid
469
470 // Material
474
475 // Visibility
483}
484
485
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
static TOOL_ACTION zoomRedraw
Definition: actions.h:131
static TOOL_ACTION zoomOutCenter
Definition: actions.h:135
static TOOL_ACTION zoomIn
Definition: actions.h:132
static TOOL_ACTION zoomOut
Definition: actions.h:133
static TOOL_ACTION panDown
Definition: actions.h:182
CURSOR_EVENT_TYPE
Definition: actions.h:300
@ CURSOR_RIGHT
Definition: actions.h:308
@ CURSOR_LEFT
Definition: actions.h:306
@ CURSOR_UP
Definition: actions.h:302
@ CURSOR_DOWN
Definition: actions.h:304
static TOOL_ACTION panLeft
Definition: actions.h:183
static TOOL_ACTION updateMenu
Definition: actions.h:267
static TOOL_ACTION zoomFitScreen
Definition: actions.h:141
static TOOL_ACTION panUp
Definition: actions.h:181
static TOOL_ACTION zoomInCenter
Definition: actions.h:134
static TOOL_ACTION panRight
Definition: actions.h:184
Define the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void UpdateAll()
Run update handlers for the menu and its submenus.
void OnLayerVisibilityChanged(int aLayer, bool isVisible)
std::bitset< LAYER_3D_END > GetVisibleLayers() const
EDA_3D_VIEWER_SETTINGS * m_Cfg
void RotateY(float aAngleInRadians)
Definition: camera.cpp:666
void RotateX(float aAngleInRadians)
Definition: camera.cpp:659
void RotateZ(float aAngleInRadians)
Definition: camera.cpp:673
void ToggleProjection()
Definition: camera.cpp:560
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.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:61
bool IsQuasiModal() const
Definition: dialog_shim.h:86
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 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.
Definition: eda_3d_canvas.h:51
void DisplayStatus()
Update the status bar with the position information.
void RenderRaytracingRequest()
Request to render the current view in Raytracing mode.
bool SetView3D(VIEW3D_TYPE aRequestedView)
Select a specific 3D view or operation.
void RenderEngineChanged()
Notify that the render engine was changed.
void Request_refresh(bool aRedrawImmediately=true)
Schedule a refresh update of the canvas.
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 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.
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
EDA_3D_CANVAS * GetCanvas()
BOARD_ADAPTER & GetAdapter()
APPEARANCE_CONTROLS_3D * GetAppearanceManager()
void ExportImage(EDA_3D_VIEWER_EXPORT_FORMAT aFormat, const wxSize &aSize)
Export 3D viewer image to file or clipboard.
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.
Definition: kiway_holder.h:39
HOLDER_TYPE GetType() const
Definition: kiway_holder.h:48
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:220
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:168
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:82
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:465
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.
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:406
#define EDA_3D_CANVAS_ID
Definition: eda_3d_canvas.h:45
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:605
@ LAYER_3D_BOUNDING_BOXES
Definition: layer_ids.h:606
@ LAYER_3D_SMD_MODELS
Definition: layer_ids.h:601
@ LAYER_3D_TH_MODELS
Definition: layer_ids.h:600
@ LAYER_3D_VIRTUAL_MODELS
Definition: layer_ids.h:602
@ LAYER_3D_MODELS_MARKED_DNP
Definition: layer_ids.h:604
@ LAYER_3D_MODELS_NOT_IN_POS
Definition: layer_ids.h:603
#define PANEL_PREVIEW_3D_MODEL_ID
@ BUT_RIGHT
Definition: tool_event.h:133