KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eda_3d_viewer_frame.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) 2015-2016 Mario Luzeiro <[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <wx/filename.h>
27#include <wx/msgdlg.h>
28#include <wx/string.h>
29#include <wx/wupdlock.h>
30#include <wx/clipbrd.h>
31#include <wx/filedlg.h>
32#include <wx/dialog.h>
33#include "eda_3d_viewer_frame.h"
37#include <3d_viewer_id.h>
41#include <board.h>
42#include <advanced_config.h>
43#include <bitmaps.h>
45#include <core/arraydim.h>
46#include <dpi_scaling_common.h>
47#include <pgm_base.h>
48#include <project.h>
52#include <tool/action_manager.h>
53#include <tool/common_control.h>
54#include <tool/tool_manager.h>
56#include <tool/action_toolbar.h>
57#include <widgets/wx_infobar.h>
60#include <project_pcb.h>
61
63
71const wxChar* EDA_3D_VIEWER_FRAME::m_logTrace = wxT( "KI_TRACE_EDA_3D_VIEWER" );
72
73
74BEGIN_EVENT_TABLE( EDA_3D_VIEWER_FRAME, KIWAY_PLAYER )
75
77 EVT_SET_FOCUS( EDA_3D_VIEWER_FRAME::OnSetFocus )
78
80 EDA_3D_VIEWER_FRAME::Process_Special_Functions )
81
82 EVT_MENU( wxID_CLOSE, EDA_3D_VIEWER_FRAME::Exit3DFrame )
83 EVT_MENU( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER_FRAME::onRenderEngineSelection )
84 EVT_MENU( ID_DISABLE_RAY_TRACING, EDA_3D_VIEWER_FRAME::onDisableRayTracing )
85
86 EVT_CLOSE( EDA_3D_VIEWER_FRAME::OnCloseWindow )
87END_EVENT_TABLE()
88
89
91 const wxString& aTitle, long style ) :
92 KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle, wxDefaultPosition,
93 wxDefaultSize, style, QUALIFIED_VIEWER3D_FRAMENAME( aParent ), unityScale ),
94 m_mainToolBar( nullptr ),
95 m_canvas( nullptr ),
96 m_currentCamera( m_trackBallCamera ),
97 m_trackBallCamera( 2 * RANGE_SCALE_3D ),
98 m_spaceMouse( nullptr )
99{
100 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME %s" ), aTitle );
101
102 m_disable_ray_tracing = false;
103 m_aboutTitle = _HKI( "KiCad 3D Viewer" );
104
105 // Give it an icon
106 wxIcon icon;
107 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_3d ) );
108 SetIcon( icon );
109
110 // Create the status line
111 static const int status_dims[5] = { -1, 170, 130, 130, 130 };
112
113 wxStatusBar *status_bar = CreateStatusBar( arrayDim( status_dims ) );
114 SetStatusWidths( arrayDim( status_dims ), status_dims );
115
118 ANTIALIASING_MODE aaMode = static_cast<ANTIALIASING_MODE>( cfg->m_Render.opengl_AA_mode );
119
120 m_canvas = new EDA_3D_CANVAS( this, OGL_ATT_LIST::GetAttributesList( aaMode, true ),
121 m_boardAdapter, m_currentCamera,
123
124 m_appearancePanel = new APPEARANCE_CONTROLS_3D( this, GetCanvas() );
125
126 LoadSettings( cfg );
127 loadCommonSettings();
128
129 m_appearancePanel->SetUserViewports( Prj().GetProjectFile().m_Viewports3D );
130
131 // Create the manager
132 m_toolManager = new TOOL_MANAGER;
133 m_toolManager->SetEnvironment( GetBoard(), nullptr, nullptr, cfg, this );
134
135 m_actions = new EDA_3D_ACTIONS();
136 m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
137 m_canvas->SetEventDispatcher( m_toolDispatcher );
138
139 // Register tools
140 m_toolManager->RegisterTool( new COMMON_CONTROL );
141 m_toolManager->RegisterTool( new EDA_3D_CONTROLLER );
142 m_toolManager->InitTools();
143
144 setupUIConditions();
145
146 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
147 ctrlTool->SetRotationIncrement( cfg->m_Camera.rotation_increment );
148
149 // Run the viewer control tool, it is supposed to be always active
150 m_toolManager->InvokeTool( "3DViewer.Control" );
151
152 ReCreateMenuBar();
153 ReCreateMainToolbar();
154
155 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
156
157 m_auimgr.SetManagedWindow( this );
158
159 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( wxS( "MainToolbar" ) )
160 .Top().Layer( 6 ) );
161 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) )
162 .Top().Layer( 1 ) );
163 m_auimgr.AddPane( m_appearancePanel, EDA_PANE().Name( "LayersManager" )
164 .Right().Layer( 3 )
165 .Caption( _( "Appearance" ) ).PaneBorder( false )
166 .MinSize( 180, -1 ).BestSize( 190, -1 ) );
167 m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) )
168 .Center() );
169
170 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
171
172 if( cfg->m_AuiPanels.right_panel_width > 0 )
173 SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 );
174
175 layersManager.Show( cfg->m_AuiPanels.show_layer_manager );
176
177 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
178 // hiding it.
179 m_auimgr.Update();
180
181 // We don't want the infobar displayed right away
182 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
183 m_auimgr.Update();
184
185 m_canvas->SetInfoBar( m_infoBar );
186 m_canvas->SetStatusBar( status_bar );
187
188 try
189 {
190 m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas );
191 }
192 catch( const std::system_error& e )
193 {
194 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
195 }
196
197 // Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
198 // in order to receive mouse events. Otherwise, the user has to click somewhere on
199 // the canvas before it will respond to mouse wheel events.
200 m_canvas->SetFocus();
201}
202
203
205{
206 delete m_spaceMouse;
207
209
210 m_canvas->SetEventDispatcher( nullptr );
211
212 m_auimgr.UnInit();
213}
214
215
217{
219
222
223// Helper to define check conditions
224#define GridSizeCheck( x ) ACTION_CONDITIONS().Check( cond.GridSize( x ) )
225
226 auto raytracing =
227 [this]( const SELECTION& aSel )
228 {
229 return m_boardAdapter.m_Cfg->m_Render.engine != RENDER_ENGINE::OPENGL;
230 };
231 auto showTH =
232 [this]( const SELECTION& aSel )
233 {
235 };
236 auto showSMD =
237 [this]( const SELECTION& aSel )
238 {
240 };
241 auto showVirtual =
242 [this]( const SELECTION& aSel )
243 {
245 };
246 auto show_NotInPosfile =
247 [this]( const SELECTION& aSel )
248 {
250 };
251 auto show_DNP =
252 [this]( const SELECTION& aSel )
253 {
255 };
256 auto showBBoxes =
257 [this]( const SELECTION& aSel )
258 {
260 };
261 auto showAxes =
262 [this]( const SELECTION& aSel )
263 {
265 };
266 auto ortho =
267 [this]( const SELECTION& )
268 {
269 return m_currentCamera.GetProjection() == PROJECTION_TYPE::ORTHO;
270 };
271
272 auto appearances =
273 [this]( const SELECTION& aSel )
274 {
276 };
277
279
281 mgr->SetConditions( EDA_3D_ACTIONS::showSMD, ACTION_CONDITIONS().Check( showSMD ) );
282 mgr->SetConditions( EDA_3D_ACTIONS::showVirtual, ACTION_CONDITIONS().Check( showVirtual ) );
283 mgr->SetConditions( EDA_3D_ACTIONS::showNotInPosFile, ACTION_CONDITIONS().Check( show_NotInPosfile ) );
284 mgr->SetConditions( EDA_3D_ACTIONS::showDNP, ACTION_CONDITIONS().Check( show_DNP ) );
285
286 mgr->SetConditions( EDA_3D_ACTIONS::showBBoxes, ACTION_CONDITIONS().Check( showBBoxes ) );
287 mgr->SetConditions( EDA_3D_ACTIONS::showAxis, ACTION_CONDITIONS().Check( showAxes ) );
288
289 mgr->SetConditions( EDA_3D_ACTIONS::noGrid, GridSizeCheck( GRID3D_TYPE::NONE ) );
290 mgr->SetConditions( EDA_3D_ACTIONS::show10mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_10MM ) );
291 mgr->SetConditions( EDA_3D_ACTIONS::show5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_5MM ) );
292 mgr->SetConditions( EDA_3D_ACTIONS::show2_5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_2P5MM ) );
293 mgr->SetConditions( EDA_3D_ACTIONS::show1mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_1MM ) );
295
297
298#undef GridSizeCheck
299}
300
301
302bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent )
303{
304 static bool s_presetSwitcherShown = false;
305 static bool s_viewportSwitcherShown = false;
306
307 // wxWidgets generates no key events for the tab key when the ctrl key is held down. One
308 // way around this is to look at all events and inspect the keyboard state of the tab key.
309 // However, this runs into issues on some linux VMs where querying the keyboard state is
310 // very slow. Fortunately we only use ctrl-tab on Mac, so we implement this lovely hack:
311#ifdef __WXMAC__
312 if( wxGetKeyState( WXK_TAB ) )
313#else
314 if( ( aEvent.GetEventType() == wxEVT_CHAR || aEvent.GetEventType() == wxEVT_CHAR_HOOK )
315 && static_cast<wxKeyEvent&>( aEvent ).GetKeyCode() == WXK_TAB )
316#endif
317 {
318 if( !s_presetSwitcherShown && wxGetKeyState( PRESET_SWITCH_KEY ) )
319 {
320 if( m_appearancePanel && this->IsActive() )
321 {
322 wxArrayString mru = m_appearancePanel->GetLayerPresetsMRU();
323
324 if( mru.size() > 0 )
325 {
326 for( wxString& str : mru )
327 {
328 if( str == FOLLOW_PCB )
329 str = _( "Follow PCB Editor" );
330 else if( str == FOLLOW_PLOT_SETTINGS )
331 str = _( "Follow PCB Plot Settings" );
332 }
333
334 EDA_VIEW_SWITCHER switcher( this, mru, PRESET_SWITCH_KEY );
335
336 s_presetSwitcherShown = true;
337 switcher.ShowModal();
338 s_presetSwitcherShown = false;
339
340 int idx = switcher.GetSelection();
341
342 if( idx >= 0 && idx < (int) mru.size() )
343 {
344 wxString internalName = m_appearancePanel->GetLayerPresetsMRU()[idx];
345 m_appearancePanel->ApplyLayerPreset( internalName );
346 }
347
348 return true;
349 }
350 }
351 }
352 else if( !s_viewportSwitcherShown && wxGetKeyState( VIEWPORT_SWITCH_KEY ) )
353 {
354 if( this->IsActive() )
355 {
356 const wxArrayString& viewportMRU = m_appearancePanel->GetViewportsMRU();
357
358 if( viewportMRU.size() > 0 )
359 {
360 EDA_VIEW_SWITCHER switcher( this, viewportMRU, VIEWPORT_SWITCH_KEY );
361
362 s_viewportSwitcherShown = true;
363 switcher.ShowModal();
364 s_viewportSwitcherShown = false;
365
366 int idx = switcher.GetSelection();
367
368 if( idx >= 0 && idx < (int) viewportMRU.size() )
369 m_appearancePanel->ApplyViewport( viewportMRU[idx] );
370
371 return true;
372 }
373 }
374 }
375 }
376
377 return wxFrame::TryBefore( aEvent );
378}
379
380
381void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
382{
384
385 if( m_spaceMouse && aEvent.IsIconized() )
386 m_spaceMouse->SetFocus( false );
387}
388
389
391{
392 // This will schedule a request to load later
393 // ReloadRequest also updates the board pointer so always call it first
394 if( m_canvas )
396
399}
400
401
402void EDA_3D_VIEWER_FRAME::NewDisplay( bool aForceImmediateRedraw )
403{
404 if( m_canvas )
406
407 // After the ReloadRequest call, the refresh often takes a bit of time,
408 // and it is made here only on request.
409 if( m_canvas && aForceImmediateRedraw )
410 m_canvas->Refresh();
411}
412
413
415{
416 // Only update in OpenGL for an interactive interaction
417 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
418 m_canvas->Request_refresh( true );
419}
420
421
423{
424 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
426 else
427 NewDisplay( true );
428}
429
430
431void EDA_3D_VIEWER_FRAME::Exit3DFrame( wxCommandEvent &event )
432{
433 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Exit3DFrame" ) );
434
435 Close( true );
436}
437
438
439void EDA_3D_VIEWER_FRAME::OnCloseWindow( wxCloseEvent &event )
440{
441 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnCloseWindow" ) );
442
443 // Do not show the layer manager during closing to avoid flicker on some platforms (Windows)
444 // that generate useless redraw of items in the Layer Manager
445 if( m_auimgr.GetPane( wxS( "LayersManager" ) ).IsShown() )
446 m_auimgr.GetPane( wxS( "LayersManager" ) ).Show( false );
447
448 if( m_canvas )
449 m_canvas->Close();
450
451 Destroy();
452 event.Skip( true );
453}
454
455
457{
458 int id = event.GetId();
459 bool isChecked = event.IsChecked();
460
461 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Process_Special_Functions id %d "
462 "isChecked %d" ),
463 id,
464 isChecked );
465
466 if( m_canvas == nullptr )
467 return;
468
469 switch( id )
470 {
472 NewDisplay( true );
473 break;
474
478 takeScreenshot( event );
479 return;
480
482 {
483 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>( "3d_viewer" );
484 cfg->ResetToDefaults();
485 LoadSettings( cfg );
486
487 // Tell canvas that we (may have) changed the render engine
489
490 NewDisplay( true );
491 }
492 return;
493
494 default:
495 wxFAIL_MSG( wxT( "Invalid event in EDA_3D_VIEWER_FRAME::Process_Special_Functions()" ) );
496 return;
497 }
498}
499
500
502{
504 RENDER_ENGINE old_engine = engine;
505
506 if( old_engine == RENDER_ENGINE::OPENGL )
507 engine = RENDER_ENGINE::RAYTRACING;
508 else
509 engine = RENDER_ENGINE::OPENGL;
510
511 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ),
512 engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) );
513
514 if( old_engine != engine )
516}
517
518
519void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent )
520{
521 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ),
522 __WXFUNCTION__ );
523
525 m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
526}
527
528
529void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent )
530{
531 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnActivate" ) );
532
533 if( aEvent.GetActive() && m_canvas )
534 {
535 // Reload data if 3D frame shows a board,
536 // because it can be changed since last frame activation
539
540 // Activates again the focus of the canvas so it will catch mouse and key events
541 m_canvas->SetFocus();
542 }
543
544 if( m_spaceMouse )
545 m_spaceMouse->SetFocus( aEvent.GetActive() );
546
547 aEvent.Skip(); // required under wxMAC
548}
549
550
551void EDA_3D_VIEWER_FRAME::OnSetFocus( wxFocusEvent& aEvent )
552{
553 // Activates again the focus of the canvas so it will catch mouse and key events
554 if( m_canvas )
555 m_canvas->SetFocus();
556
557 aEvent.Skip();
558}
559
560
562{
564
565 // Dynamic_cast here will fail on Mac when called from CvPCB.
566 EDA_3D_VIEWER_SETTINGS* cfg = static_cast<EDA_3D_VIEWER_SETTINGS*>( aCfg );
567
568 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::LoadSettings" ) );
569
570 if( cfg )
571 {
572 applySettings( cfg );
573
574 if( !GetBoard()->GetProject() )
575 GetBoard()->SetProject( &Prj() );
576
578
579 // When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine
580 // because the ray tracing is very time consuming, and can be seen as not working
581 // (freeze window) with large boards.
582 m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
583
585 {
586 wxString legacyColorsPresetName = _( "legacy colors" );
587
588 cfg->m_UseStackupColors = false;
589
590 if( !cfg->FindPreset( legacyColorsPresetName ) )
591 {
592 cfg->m_LayerPresets.emplace_back( legacyColorsPresetName,
593 GetAdapter().GetDefaultVisibleLayers(),
594 GetAdapter().GetDefaultColors() );
595 }
596
598 }
599
600 m_boardAdapter.InitSettings( nullptr, nullptr );
601
604 }
605}
606
607
609{
610 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>( "3d_viewer" );
611
613
614 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::SaveSettings" ) );
615
616 wxLogTrace( m_logTrace, m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::RAYTRACING ?
617 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting Ray Trace" )
618 :
619 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting OpenGL" ) );
620
621 if( cfg )
622 {
623 cfg->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
624
625 cfg->m_Camera.animation_enabled = m_canvas->GetAnimationEnabled();
626 cfg->m_Camera.moving_speed_multiplier = m_canvas->GetMovingSpeedMultiplier();
627 cfg->m_Camera.projection_mode = m_canvas->GetProjectionMode();
628
629 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
630 cfg->m_Camera.rotation_increment = ctrlTool->GetRotationIncrement();
631 }
632}
633
634
635void EDA_3D_VIEWER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
636{
637 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::CommonSettingsChanged" ) );
638
639 // Regen menu bars, etc
640 EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
641
642 // There is no base class that handles toolbars for this frame
644
646 applySettings( Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>( "3d_viewer" ) );
647
649
650 NewDisplay( true );
651}
652
653
655{
657
658 SetTitle( _( "3D Viewer" ) );
660
662 {
663 wxAuiPaneInfo& lm_pane_info = m_auimgr.GetPane( m_appearancePanel );
664 lm_pane_info.Caption( _( "Appearance" ) );
665 }
666
667 SetStatusText( wxEmptyString, ACTIVITY );
668 SetStatusText( wxEmptyString, HOVERED_ITEM );
669}
670
671
673{
676 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
677
678 // show auxiliary Vertical layers and visibility manager toolbar
680
681 layersManager.Show( cfg->m_AuiPanels.show_layer_manager );
682
684 {
685 SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 );
686 }
687 else
688 {
690 m_auimgr.Update();
691 }
692}
693
694
696{
699}
700
701
702void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
703{
704 wxString fullFileName;
705 bool fmt_is_jpeg = false;
706
707 if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
708 fmt_is_jpeg = true;
709
710 if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
711 {
712 // Remember path between saves during this session only.
713 const wxString wildcard = fmt_is_jpeg ? FILEEXT::JpegFileWildcard() : FILEEXT::PngFileWildcard();
714 const wxString ext = fmt_is_jpeg ? FILEEXT::JpegFileExtension : FILEEXT::PngFileExtension;
715
716 // First time path is set to the project path.
719
721
722 wxFileDialog dlg( this, _( "3D Image File Name" ),
724 m_defaultSaveScreenshotFileName.GetFullName(), wildcard,
725 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
726
727 if( dlg.ShowModal() == wxID_CANCEL )
728 return;
729
730 m_defaultSaveScreenshotFileName = dlg.GetPath();
731
732 if( m_defaultSaveScreenshotFileName.GetExt().IsEmpty() )
734
735 fullFileName = m_defaultSaveScreenshotFileName.GetFullPath();
736
737 wxFileName fn = fullFileName;
738
739 if( !fn.IsDirWritable() )
740 {
741 wxString msg;
742
743 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fullFileName );
744 wxMessageBox( msg, _( "Error" ), wxOK | wxICON_ERROR, this );
745 return;
746 }
747
748 // Be sure the screen area destroyed by the file dialog is redrawn
749 // before making a screen copy.
750 // Without this call, under Linux the screen refresh is made to late.
751 wxYield();
752 }
753
754 // Be sure we have the latest 3D view (remember 3D view is buffered)
755 // Also ensure any highlighted item is not highlighted when creating screen shot
757 bool allow_highlight = cfg.highlight_on_rollover;
758 cfg.highlight_on_rollover = false;
759
760 m_canvas->DoRePaint(); // init first buffer
761 m_canvas->DoRePaint(); // init second buffer
762
763 // Build image from the 3D buffer
764 wxWindowUpdateLocker noUpdates( this );
765
766 wxImage screenshotImage;
767
768 if( m_canvas )
769 m_canvas->GetScreenshot( screenshotImage );
770
771 cfg.highlight_on_rollover = allow_highlight;
772
773 if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
774 {
775 wxBitmap bitmap( screenshotImage );
776
777 wxLogNull doNotLog; // disable logging of failed clipboard actions
778
779 if( wxTheClipboard->Open() )
780 {
781 wxBitmapDataObject* dobjBmp = new wxBitmapDataObject( bitmap );
782
783 if( !wxTheClipboard->SetData( dobjBmp ) )
784 wxMessageBox( _( "Failed to copy image to clipboard" ) );
785
786 wxTheClipboard->Flush(); /* the data in clipboard will stay
787 * available after the application exits */
788 wxTheClipboard->Close();
789 }
790 }
791 else
792 {
793 if( !screenshotImage.SaveFile( fullFileName,
794 fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
795 wxMessageBox( _( "Can't save file" ) );
796
797 screenshotImage.Destroy();
798 }
799}
800
801
803{
804 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::RenderEngineChanged()" ) );
805
806 if( m_canvas )
808}
809
810
812{
813 wxCHECK_RET( m_canvas, wxT( "Cannot load settings to null canvas" ) );
814
815 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
816
817 // TODO(JE) use all control options
819}
820
821
823{
824 m_boardAdapter.m_Cfg = cfg;
825
829
831}
RENDER_ENGINE
Render engine mode.
Definition: 3d_enums.h:64
@ ID_MENU_SCREENCOPY_PNG
Definition: 3d_viewer_id.h:40
@ ID_DISABLE_RAY_TRACING
Definition: 3d_viewer_id.h:51
@ ID_START_COMMAND_3D
Definition: 3d_viewer_id.h:36
@ ID_MENU_COMMAND_END
Definition: 3d_viewer_id.h:47
@ ID_RELOAD3D_BOARD
Definition: 3d_viewer_id.h:37
@ ID_TOOL_SCREENCOPY_TOCLIBBOARD
Definition: 3d_viewer_id.h:38
@ ID_MENU3D_RESET_DEFAULTS
Definition: 3d_viewer_id.h:44
@ ID_RENDER_CURRENT_VIEW
Definition: 3d_viewer_id.h:49
@ ID_MENU_SCREENCOPY_JPEG
Definition: 3d_viewer_id.h:41
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
constexpr EDA_IU_SCALE unityScale
Definition: base_units.h:111
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:66
Manage TOOL_ACTION objects.
void SetConditions(const TOOL_ACTION &aAction, const ACTION_CONDITIONS &aConditions)
Set the conditions the UI elements for activating a specific tool action should use for determining t...
std::vector< VIEWPORT3D > GetUserViewports() const
Update the current viewports from those saved in the project file.
void ApplyViewport(const wxString &aPresetName)
const wxArrayString & GetViewportsMRU()
void ApplyLayerPreset(const wxString &aPresetName)
const wxArrayString & GetLayerPresetsMRU()
Return a list of viewports created by the user.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:92
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
Function to be called by the render when it need to reload the settings for the board.
void SetBoard(BOARD *aBoard) noexcept
Set current board to be rendered.
EDA_3D_VIEWER_SETTINGS * m_Cfg
bool m_MousewheelPanning
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:197
PROJECTION_TYPE GetProjection()
Definition: camera.h:205
Handle actions that are shared between different applications.
int ShowModal() override
EDA_3D_ACTIONS.
static TOOL_ACTION showLayersManager
static TOOL_ACTION showNotInPosFile
static TOOL_ACTION showTHT
static TOOL_ACTION noGrid
static TOOL_ACTION show2_5mmGrid
static TOOL_ACTION show1mmGrid
static TOOL_ACTION showDNP
static TOOL_ACTION toggleOrtho
static TOOL_ACTION show10mmGrid
static TOOL_ACTION show5mmGrid
static TOOL_ACTION showSMD
static TOOL_ACTION showVirtual
static TOOL_ACTION showBBoxes
static TOOL_ACTION showAxis
Implement a canvas based on a wxGLCanvas.
Definition: eda_3d_canvas.h:49
int GetMovingSpeedMultiplier() const
void SetProjectionMode(int aMode)
void SetAnimationEnabled(bool aEnable)
Enable or disable camera animation when switching to a pre-defined view.
int GetProjectionMode() const
void DoRePaint()
The actual function to repaint the canvas.
void SetEventDispatcher(TOOL_DISPATCHER *aEventDispatcher)
Set a dispatcher that processes events and forwards them to tools.
bool IsReloadRequestPending() const
Query if there is a pending reload request.
Definition: eda_3d_canvas.h:91
bool GetAnimationEnabled() const
void ReloadRequest(BOARD *aBoard=nullptr, S3D_CACHE *aCachePointer=nullptr)
void GetScreenshot(wxImage &aDstImage)
Request a screenshot and output it to the aDstImage.
void SetMovingSpeedMultiplier(int aMultiplier)
Set the camera animation moving speed multiplier option.
void RenderEngineChanged()
Notify that the render engine was changed.
void Request_refresh(bool aRedrawImmediately=true)
Schedule a refresh update of the canvas.
EDA_3D_CONTROLLER.
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
void OnSetFocus(wxFocusEvent &event)
void onDisableRayTracing(wxCommandEvent &aEvent)
void takeScreenshot(wxCommandEvent &event)
Create a Screenshot of the current 3D view.
void applySettings(EDA_3D_VIEWER_SETTINGS *aSettings)
BOARD_ADAPTER & GetAdapter() override
PCB_BASE_FRAME * Parent() const
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
void setupUIConditions() override
Setup the UI conditions for the various actions and their controls in this frame.
void OnActivate(wxActivateEvent &event)
bool TryBefore(wxEvent &aEvent) override
EDA_3D_CANVAS * m_canvas
void Exit3DFrame(wxCommandEvent &event)
Called when user press the File->Exit.
BOARD_ADAPTER m_boardAdapter
void RenderEngineChanged()
RenderEngineChanged - Update toolbar icon and call canvas RenderEngineChanged.
void Process_Special_Functions(wxCommandEvent &event)
void OnCloseWindow(wxCloseEvent &event)
void ReCreateMainToolbar()
Definition: 3d_toolbar.cpp:38
void ShowChangedLanguage() override
void ReloadRequest()
Request reloading the 3D view.
wxFileName m_defaultSaveScreenshotFileName
void onRenderEngineSelection(wxCommandEvent &event)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
NL_3D_VIEWER_PLUGIN * m_spaceMouse
void loadCommonSettings()
Load configuration from common settings.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification that common settings are updated.
void handleIconizeEvent(wxIconizeEvent &aEvent) override
Handle a window iconize event.
LAYER_PRESET_3D * FindPreset(const wxString &aName)
std::vector< LAYER_PRESET_3D > m_LayerPresets
virtual void handleIconizeEvent(wxIconizeEvent &aEvent)
Handle a window iconize event.
APPEARANCE_CONTROLS_3D * m_appearancePanel
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
SETTINGS_MANAGER * GetSettingsManager() const
wxAuiManager m_auimgr
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
virtual void RegisterUIUpdateHandler(int aID, const ACTION_CONDITIONS &aConditions) override
Register a UI update handler for the control with ID aID.
static KIGFX::VC_SETTINGS GetVcSettings()
Gets a populated View Controls settings object dervived from our program settings.
Specialization of the wxAuiPaneInfo class for KiCad panels.
int GetSelection() const
void SetVcSettings(const KIGFX::VC_SETTINGS &aVcSettings)
void ResetToDefaults()
Resets all parameters to default values.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:284
The class that implements the public interface to the SpaceMouse plug-in.
void SetFocus(bool aFocus=true)
Set the connection to the 3Dconnexion driver to the focus state so that 3DMouse data is routed here.
static const wxGLAttributes GetAttributesList(ANTIALIASING_MODE aAntiAliasingMode, bool aAlpha=false)
Get a list of attributes to pass to wxGLCanvas.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:679
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
std::vector< VIEWPORT3D > m_Viewports3D
List of stored viewports (pos + zoom)
Definition: project_file.h:183
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
Definition: project_pcb.cpp:77
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:129
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:167
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Master controller class:
Definition: tool_manager.h:62
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:302
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:76
#define _HKI(x)
#define _(s)
#define GridSizeCheck(x)
EVT_TOOL_RANGE(ID_START_COMMAND_3D, ID_MENU_COMMAND_END, EDA_3D_VIEWER_FRAME::Process_Special_Functions) EDA_3D_VIEWER_FRAME
Declaration of the eda_3d_viewer class.
@ ACTIVITY
@ HOVERED_ITEM
#define FOLLOW_PLOT_SETTINGS
#define LEGACY_PRESET_FLAG
#define FOLLOW_PCB
#define QUALIFIED_VIEWER3D_FRAMENAME(parent)
#define VIEWPORT_SWITCH_KEY
#define PRESET_SWITCH_KEY
@ FRAME_PCB_DISPLAY3D
Definition: frame_type.h:47
static const std::string JpegFileExtension
static const std::string PngFileExtension
static wxString PngFileWildcard()
static wxString JpegFileWildcard()
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
PROJECT & Prj()
Definition: kicad.cpp:595
Declaration of the NL_3D_VIEWER_PLUGIN class.
ANTIALIASING_MODE
Anti-aliasing options.
Definition: ogl_attr_list.h:37
BOARD * GetBoard()
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
Definition of file extensions used in Kicad.
void SetAuiPaneSize(wxAuiManager &aManager, wxAuiPaneInfo &aPane, int aWidth, int aHeight)
Sets the size of an AUI pane, working around http://trac.wxwidgets.org/ticket/13180.