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 <advanced_config.h>
42#include <bitmaps.h>
44#include <core/arraydim.h>
45#include <dpi_scaling_common.h>
46#include <pgm_base.h>
47#include <project.h>
51#include <tool/action_manager.h>
52#include <tool/common_control.h>
53#include <tool/tool_manager.h>
55#include <tool/action_toolbar.h>
56#include <widgets/wx_infobar.h>
59#include <project_pcb.h>
60
62
70const wxChar* EDA_3D_VIEWER_FRAME::m_logTrace = wxT( "KI_TRACE_EDA_3D_VIEWER" );
71
72
73BEGIN_EVENT_TABLE( EDA_3D_VIEWER_FRAME, KIWAY_PLAYER )
74
76 EVT_SET_FOCUS( EDA_3D_VIEWER_FRAME::OnSetFocus )
77
79 EDA_3D_VIEWER_FRAME::Process_Special_Functions )
80
81 EVT_MENU( wxID_CLOSE, EDA_3D_VIEWER_FRAME::Exit3DFrame )
82 EVT_MENU( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER_FRAME::onRenderEngineSelection )
83 EVT_MENU( ID_DISABLE_RAY_TRACING, EDA_3D_VIEWER_FRAME::onDisableRayTracing )
84
85 EVT_CLOSE( EDA_3D_VIEWER_FRAME::OnCloseWindow )
86END_EVENT_TABLE()
87
88
90 const wxString& aTitle, long style ) :
91 KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle, wxDefaultPosition,
92 wxDefaultSize, style, QUALIFIED_VIEWER3D_FRAMENAME( aParent ), unityScale ),
93 m_mainToolBar( nullptr ),
94 m_canvas( nullptr ),
95 m_currentCamera( m_trackBallCamera ),
96 m_trackBallCamera( 2 * RANGE_SCALE_3D ),
97 m_spaceMouse( nullptr )
98{
99 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME %s" ), aTitle );
100
101 m_disable_ray_tracing = false;
102 m_aboutTitle = _HKI( "KiCad 3D Viewer" );
103
104 // Give it an icon
105 wxIcon icon;
106 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_3d ) );
107 SetIcon( icon );
108
109 // Create the status line
110 static const int status_dims[5] = { -1, 170, 130, 130, 130 };
111
112 wxStatusBar *status_bar = CreateStatusBar( arrayDim( status_dims ) );
113 SetStatusWidths( arrayDim( status_dims ), status_dims );
114
115 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
117 ANTIALIASING_MODE aaMode = static_cast<ANTIALIASING_MODE>( cfg->m_Render.opengl_AA_mode );
118
119 m_canvas = new EDA_3D_CANVAS( this, OGL_ATT_LIST::GetAttributesList( aaMode, true ),
120 m_boardAdapter, m_currentCamera,
122
123 m_appearancePanel = new APPEARANCE_CONTROLS_3D( this, GetCanvas() );
124
125 LoadSettings( cfg );
126 loadCommonSettings();
127
128 m_appearancePanel->SetUserViewports( Prj().GetProjectFile().m_Viewports3D );
129
130 // Create the manager
131 m_toolManager = new TOOL_MANAGER;
132 m_toolManager->SetEnvironment( GetBoard(), nullptr, nullptr, cfg, this );
133
134 m_actions = new EDA_3D_ACTIONS();
135 m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
136 m_canvas->SetEventDispatcher( m_toolDispatcher );
137
138 // Register tools
139 m_toolManager->RegisterTool( new COMMON_CONTROL );
140 m_toolManager->RegisterTool( new EDA_3D_CONTROLLER );
141 m_toolManager->InitTools();
142
143 setupUIConditions();
144
145 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
146 ctrlTool->SetRotationIncrement( cfg->m_Camera.rotation_increment );
147
148 // Run the viewer control tool, it is supposed to be always active
149 m_toolManager->InvokeTool( "3DViewer.Control" );
150
151 ReCreateMenuBar();
152 ReCreateMainToolbar();
153
154 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
155
156 m_auimgr.SetManagedWindow( this );
157
158 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( wxS( "MainToolbar" ) )
159 .Top().Layer( 6 ) );
160 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) )
161 .Top().Layer( 1 ) );
162 m_auimgr.AddPane( m_appearancePanel, EDA_PANE().Name( "LayersManager" )
163 .Right().Layer( 3 )
164 .Caption( _( "Appearance" ) ).PaneBorder( false )
165 .MinSize( 180, -1 ).BestSize( 190, -1 ) );
166 m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) )
167 .Center() );
168
169 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
170
171 if( cfg->m_AuiPanels.right_panel_width > 0 )
172 SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 );
173
174 layersManager.Show( cfg->m_AuiPanels.show_layer_manager );
175
176 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
177 // hiding it.
178 m_auimgr.Update();
179
180 // We don't want the infobar displayed right away
181 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
182 m_auimgr.Update();
183
184 m_canvas->SetInfoBar( m_infoBar );
185 m_canvas->SetStatusBar( status_bar );
186
187 try
188 {
189 m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas );
190 }
191 catch( const std::system_error& e )
192 {
193 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
194 }
195
196 // Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
197 // in order to receive mouse events. Otherwise, the user has to click somewhere on
198 // the canvas before it will respond to mouse wheel events.
199 m_canvas->SetFocus();
200}
201
202
204{
205 delete m_spaceMouse;
206
208
209 m_canvas->SetEventDispatcher( nullptr );
210
211 m_auimgr.UnInit();
212}
213
214
216{
218
221
222// Helper to define check conditions
223#define GridSizeCheck( x ) ACTION_CONDITIONS().Check( cond.GridSize( x ) )
224
225 auto raytracing =
226 [this]( const SELECTION& aSel )
227 {
228 return m_boardAdapter.m_Cfg->m_Render.engine != RENDER_ENGINE::OPENGL;
229 };
230 auto showTH =
231 [this]( const SELECTION& aSel )
232 {
234 };
235 auto showSMD =
236 [this]( const SELECTION& aSel )
237 {
239 };
240 auto showVirtual =
241 [this]( const SELECTION& aSel )
242 {
244 };
245 auto show_NotInPosfile =
246 [this]( const SELECTION& aSel )
247 {
249 };
250 auto show_DNP =
251 [this]( const SELECTION& aSel )
252 {
254 };
255 auto showBBoxes =
256 [this]( const SELECTION& aSel )
257 {
259 };
260 auto showAxes =
261 [this]( const SELECTION& aSel )
262 {
264 };
265 auto ortho =
266 [this]( const SELECTION& )
267 {
268 return m_currentCamera.GetProjection() == PROJECTION_TYPE::ORTHO;
269 };
270
271 auto appearances =
272 [this]( const SELECTION& aSel )
273 {
275 };
276
278
280 mgr->SetConditions( EDA_3D_ACTIONS::showSMD, ACTION_CONDITIONS().Check( showSMD ) );
281 mgr->SetConditions( EDA_3D_ACTIONS::showVirtual, ACTION_CONDITIONS().Check( showVirtual ) );
282 mgr->SetConditions( EDA_3D_ACTIONS::showNotInPosFile, ACTION_CONDITIONS().Check( show_NotInPosfile ) );
283 mgr->SetConditions( EDA_3D_ACTIONS::showDNP, ACTION_CONDITIONS().Check( show_DNP ) );
284
285 mgr->SetConditions( EDA_3D_ACTIONS::showBBoxes, ACTION_CONDITIONS().Check( showBBoxes ) );
286 mgr->SetConditions( EDA_3D_ACTIONS::showAxis, ACTION_CONDITIONS().Check( showAxes ) );
287
288 mgr->SetConditions( EDA_3D_ACTIONS::noGrid, GridSizeCheck( GRID3D_TYPE::NONE ) );
289 mgr->SetConditions( EDA_3D_ACTIONS::show10mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_10MM ) );
290 mgr->SetConditions( EDA_3D_ACTIONS::show5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_5MM ) );
291 mgr->SetConditions( EDA_3D_ACTIONS::show2_5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_2P5MM ) );
292 mgr->SetConditions( EDA_3D_ACTIONS::show1mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_1MM ) );
294
296
297#undef GridSizeCheck
298}
299
300
301bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent )
302{
303 static bool s_presetSwitcherShown = false;
304 static bool s_viewportSwitcherShown = false;
305
306 // wxWidgets generates no key events for the tab key when the ctrl key is held down. One
307 // way around this is to look at all events and inspect the keyboard state of the tab key.
308 // However, this runs into issues on some linux VMs where querying the keyboard state is
309 // very slow. Fortunately we only use ctrl-tab on Mac, so we implement this lovely hack:
310#ifdef __WXMAC__
311 if( wxGetKeyState( WXK_TAB ) )
312#else
313 if( ( aEvent.GetEventType() == wxEVT_CHAR || aEvent.GetEventType() == wxEVT_CHAR_HOOK )
314 && static_cast<wxKeyEvent&>( aEvent ).GetKeyCode() == WXK_TAB )
315#endif
316 {
317 if( !s_presetSwitcherShown && wxGetKeyState( PRESET_SWITCH_KEY ) )
318 {
319 if( m_appearancePanel && this->IsActive() )
320 {
321 wxArrayString mru = m_appearancePanel->GetLayerPresetsMRU();
322
323 if( mru.size() > 0 )
324 {
325 for( wxString& str : mru )
326 {
327 if( str == FOLLOW_PCB )
328 str = _( "Follow PCB Editor" );
329 else if( str == FOLLOW_PLOT_SETTINGS )
330 str = _( "Follow PCB Plot Settings" );
331 }
332
333 EDA_VIEW_SWITCHER switcher( this, mru, PRESET_SWITCH_KEY );
334
335 s_presetSwitcherShown = true;
336 switcher.ShowModal();
337 s_presetSwitcherShown = false;
338
339 int idx = switcher.GetSelection();
340
341 if( idx >= 0 && idx < (int) mru.size() )
342 {
343 wxString internalName = m_appearancePanel->GetLayerPresetsMRU()[idx];
344 m_appearancePanel->ApplyLayerPreset( internalName );
345 }
346
347 return true;
348 }
349 }
350 }
351 else if( !s_viewportSwitcherShown && wxGetKeyState( VIEWPORT_SWITCH_KEY ) )
352 {
353 if( this->IsActive() )
354 {
355 const wxArrayString& viewportMRU = m_appearancePanel->GetViewportsMRU();
356
357 if( viewportMRU.size() > 0 )
358 {
359 EDA_VIEW_SWITCHER switcher( this, viewportMRU, VIEWPORT_SWITCH_KEY );
360
361 s_viewportSwitcherShown = true;
362 switcher.ShowModal();
363 s_viewportSwitcherShown = false;
364
365 int idx = switcher.GetSelection();
366
367 if( idx >= 0 && idx < (int) viewportMRU.size() )
368 m_appearancePanel->ApplyViewport( viewportMRU[idx] );
369
370 return true;
371 }
372 }
373 }
374 }
375
376 return wxFrame::TryBefore( aEvent );
377}
378
379
380void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
381{
383
384 if( m_spaceMouse && aEvent.IsIconized() )
385 m_spaceMouse->SetFocus( false );
386}
387
388
390{
391 // This will schedule a request to load later
392 // ReloadRequest also updates the board pointer so always call it first
393 if( m_canvas )
395
398}
399
400
401void EDA_3D_VIEWER_FRAME::NewDisplay( bool aForceImmediateRedraw )
402{
403 if( m_canvas )
405
406 // After the ReloadRequest call, the refresh often takes a bit of time,
407 // and it is made here only on request.
408 if( m_canvas && aForceImmediateRedraw )
409 m_canvas->Refresh();
410}
411
412
414{
415 // Only update in OpenGL for an interactive interaction
416 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
417 m_canvas->Request_refresh( true );
418}
419
420
422{
423 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
425 else
426 NewDisplay( true );
427}
428
429
430void EDA_3D_VIEWER_FRAME::Exit3DFrame( wxCommandEvent &event )
431{
432 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Exit3DFrame" ) );
433
434 Close( true );
435}
436
437
438void EDA_3D_VIEWER_FRAME::OnCloseWindow( wxCloseEvent &event )
439{
440 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnCloseWindow" ) );
441
442 // Do not show the layer manager during closing to avoid flicker on some platforms (Windows)
443 // that generate useless redraw of items in the Layer Manager
444 if( m_auimgr.GetPane( wxS( "LayersManager" ) ).IsShown() )
445 m_auimgr.GetPane( wxS( "LayersManager" ) ).Show( false );
446
447 if( m_canvas )
448 m_canvas->Close();
449
450 Destroy();
451 event.Skip( true );
452}
453
454
456{
457 int id = event.GetId();
458 bool isChecked = event.IsChecked();
459
460 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Process_Special_Functions id %d "
461 "isChecked %d" ),
462 id,
463 isChecked );
464
465 if( m_canvas == nullptr )
466 return;
467
468 switch( id )
469 {
471 NewDisplay( true );
472 break;
473
477 takeScreenshot( event );
478 return;
479
481 {
482 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
483 cfg->ResetToDefaults();
484 LoadSettings( cfg );
485
486 // Tell canvas that we (may have) changed the render engine
488
489 NewDisplay( true );
490 }
491 return;
492
493 default:
494 wxFAIL_MSG( wxT( "Invalid event in EDA_3D_VIEWER_FRAME::Process_Special_Functions()" ) );
495 return;
496 }
497}
498
499
501{
503 RENDER_ENGINE old_engine = engine;
504
505 if( old_engine == RENDER_ENGINE::OPENGL )
506 engine = RENDER_ENGINE::RAYTRACING;
507 else
508 engine = RENDER_ENGINE::OPENGL;
509
510 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ),
511 engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) );
512
513 if( old_engine != engine )
515}
516
517
518void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent )
519{
520 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ),
521 __WXFUNCTION__ );
522
524 m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
525}
526
527
528void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent )
529{
530 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnActivate" ) );
531
532 if( aEvent.GetActive() && m_canvas )
533 {
534 // Reload data if 3D frame shows a board,
535 // because it can be changed since last frame activation
538
539 // Activates again the focus of the canvas so it will catch mouse and key events
540 m_canvas->SetFocus();
541 }
542
543 if( m_spaceMouse )
544 m_spaceMouse->SetFocus( aEvent.GetActive() );
545
546 aEvent.Skip(); // required under wxMAC
547}
548
549
550void EDA_3D_VIEWER_FRAME::OnSetFocus( wxFocusEvent& aEvent )
551{
552 // Activates again the focus of the canvas so it will catch mouse and key events
553 if( m_canvas )
554 m_canvas->SetFocus();
555
556 aEvent.Skip();
557}
558
559
561{
563
564 EDA_3D_VIEWER_SETTINGS* cfg = dynamic_cast<EDA_3D_VIEWER_SETTINGS*>( aCfg );
565 wxASSERT( cfg );
566
567 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::LoadSettings" ) );
568
569 if( cfg )
570 {
571 applySettings( cfg );
572
574
575 // When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine
576 // because the ray tracing is very time consuming, and can be seen as not working
577 // (freeze window) with large boards.
578 m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
579
581 {
582 wxString legacyColorsPresetName = _( "legacy colors" );
583
584 cfg->m_UseStackupColors = false;
585
586 if( !cfg->FindPreset( legacyColorsPresetName ) )
587 {
588 cfg->m_LayerPresets.emplace_back( legacyColorsPresetName,
589 GetAdapter().GetDefaultVisibleLayers(),
590 GetAdapter().GetDefaultColors() );
591 }
592
593 cfg->m_CurrentPreset = wxEmptyString;
594 }
595
596 m_boardAdapter.InitSettings( nullptr, nullptr );
597
600 }
601}
602
603
605{
606 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
607
609
610 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::SaveSettings" ) );
611
612 wxLogTrace( m_logTrace, m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::RAYTRACING ?
613 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting Ray Trace" )
614 :
615 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting OpenGL" ) );
616
617 if( cfg )
618 {
619 cfg->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
620
621 cfg->m_Camera.animation_enabled = m_canvas->GetAnimationEnabled();
622 cfg->m_Camera.moving_speed_multiplier = m_canvas->GetMovingSpeedMultiplier();
623 cfg->m_Camera.projection_mode = m_canvas->GetProjectionMode();
624
625 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
626 cfg->m_Camera.rotation_increment = ctrlTool->GetRotationIncrement();
627 }
628}
629
630
631void EDA_3D_VIEWER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
632{
633 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::CommonSettingsChanged" ) );
634
635 // Regen menu bars, etc
636 EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
637
638 // There is no base class that handles toolbars for this frame
640
642 applySettings( Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>() );
643
645
646 NewDisplay( true );
647}
648
649
651{
653
654 SetTitle( _( "3D Viewer" ) );
656
658 {
659 wxAuiPaneInfo& lm_pane_info = m_auimgr.GetPane( m_appearancePanel );
660 lm_pane_info.Caption( _( "Appearance" ) );
661 }
662
663 SetStatusText( wxEmptyString, ACTIVITY );
664 SetStatusText( wxEmptyString, HOVERED_ITEM );
665}
666
667
669{
670 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
672 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
673
674 // show auxiliary Vertical layers and visibility manager toolbar
676
677 layersManager.Show( cfg->m_AuiPanels.show_layer_manager );
678
680 {
681 SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 );
682 }
683 else
684 {
686 m_auimgr.Update();
687 }
688}
689
690
692{
695}
696
697
698void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
699{
700 wxString fullFileName;
701 bool fmt_is_jpeg = false;
702
703 if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
704 fmt_is_jpeg = true;
705
706 if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
707 {
708 // Remember path between saves during this session only.
709 const wxString wildcard = fmt_is_jpeg ? FILEEXT::JpegFileWildcard() : FILEEXT::PngFileWildcard();
710 const wxString ext = fmt_is_jpeg ? FILEEXT::JpegFileExtension : FILEEXT::PngFileExtension;
711
712 // First time path is set to the project path.
715
717
718 wxFileDialog dlg( this, _( "3D Image File Name" ),
720 m_defaultSaveScreenshotFileName.GetFullName(), wildcard,
721 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
722
723 if( dlg.ShowModal() == wxID_CANCEL )
724 return;
725
726 m_defaultSaveScreenshotFileName = dlg.GetPath();
727
728 if( m_defaultSaveScreenshotFileName.GetExt().IsEmpty() )
730
731 fullFileName = m_defaultSaveScreenshotFileName.GetFullPath();
732
733 wxFileName fn = fullFileName;
734
735 if( !fn.IsDirWritable() )
736 {
737 wxString msg;
738
739 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fullFileName );
740 wxMessageBox( msg, _( "Error" ), wxOK | wxICON_ERROR, this );
741 return;
742 }
743
744 // Be sure the screen area destroyed by the file dialog is redrawn
745 // before making a screen copy.
746 // Without this call, under Linux the screen refresh is made to late.
747 wxYield();
748 }
749
750 // Be sure we have the latest 3D view (remember 3D view is buffered)
751 // Also ensure any highlighted item is not highlighted when creating screen shot
753 bool allow_highlight = cfg.highlight_on_rollover;
754 cfg.highlight_on_rollover = false;
755
756 m_canvas->DoRePaint(); // init first buffer
757 m_canvas->DoRePaint(); // init second buffer
758
759 // Build image from the 3D buffer
760 wxWindowUpdateLocker noUpdates( this );
761
762 wxImage screenshotImage;
763
764 if( m_canvas )
765 m_canvas->GetScreenshot( screenshotImage );
766
767 cfg.highlight_on_rollover = allow_highlight;
768
769 if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
770 {
771 wxBitmap bitmap( screenshotImage );
772
773 wxLogNull doNotLog; // disable logging of failed clipboard actions
774
775 if( wxTheClipboard->Open() )
776 {
777 wxBitmapDataObject* dobjBmp = new wxBitmapDataObject( bitmap );
778
779 if( !wxTheClipboard->SetData( dobjBmp ) )
780 wxMessageBox( _( "Failed to copy image to clipboard" ) );
781
782 wxTheClipboard->Flush(); /* the data in clipboard will stay
783 * available after the application exits */
784 wxTheClipboard->Close();
785 }
786 }
787 else
788 {
789 if( !screenshotImage.SaveFile( fullFileName,
790 fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
791 wxMessageBox( _( "Can't save file" ) );
792
793 screenshotImage.Destroy();
794 }
795}
796
797
799{
800 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::RenderEngineChanged()" ) );
801
802 if( m_canvas )
804}
805
806
808{
809 wxCHECK_RET( m_canvas, wxT( "Cannot load settings to null canvas" ) );
810
811 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
812
813 const DPI_SCALING_COMMON dpi{ settings, this };
814 m_canvas->SetScaleFactor( dpi.GetScaleFactor() );
815
816 // TODO(JE) use all control options
818}
819
820
822{
823 m_boardAdapter.m_Cfg = cfg;
824
828
830}
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:112
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
PROJECTION_TYPE GetProjection()
Definition: camera.h:205
Handle actions that are shared between different applications.
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
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 SetScaleFactor(double aFactor)
Set the canvas scale factor, probably for a hi-DPI display.
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:67
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:279
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.
std::vector< VIEWPORT3D > m_Viewports3D
List of stored viewports (pos + zoom)
Definition: project_file.h:178
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:166
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:57
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:289
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:75
#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:591
Declaration of the NL_3D_VIEWER_PLUGIN class.
ANTIALIASING_MODE
Anti-aliasing options.
Definition: ogl_attr_list.h:37
BOARD * GetBoard()
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:119
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.