KiCad PCB EDA Suite
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) 1992-2023 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 <wx/filename.h>
26#include <wx/msgdlg.h>
27#include <wx/string.h>
28#include <wx/wupdlock.h>
29#include <wx/clipbrd.h>
30#include <wx/filedlg.h>
31#include <wx/choice.h>
32#include <wx/dialog.h>
33#include "eda_3d_viewer_frame.h"
34#include "eda_list_dialog.h"
35#include "wx/generic/textdlgg.h"
38#include <3d_viewer_id.h>
42#include <bitmaps.h>
44#include <core/arraydim.h>
45#include <gal/dpi_scaling.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>
58
59#if defined( KICAD_USE_3DCONNEXION )
61#endif
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 ), m_canvas( nullptr ), m_currentCamera( m_trackBallCamera ),
94 m_viewportsLabel( nullptr ),
95 m_cbViewports( nullptr ),
96 m_trackBallCamera( 2 * RANGE_SCALE_3D ), m_spaceMouse( nullptr )
97{
98 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME %s" ), aTitle );
99
100 m_disable_ray_tracing = false;
101 m_aboutTitle = _HKI( "KiCad 3D Viewer" );
102
103 // Give it an icon
104 wxIcon icon;
105 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_3d ) );
106 SetIcon( icon );
107
108 // Create the status line
109 static const int status_dims[4] = { -1, 170, 130, 130 };
110
111 wxStatusBar *status_bar = CreateStatusBar( arrayDim( status_dims ) );
112 SetStatusWidths( arrayDim( status_dims ), status_dims );
113
114 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
116 ANTIALIASING_MODE aaMode = static_cast<ANTIALIASING_MODE>( cfg->m_Render.opengl_AA_mode );
117
118 m_canvas = new EDA_3D_CANVAS( this, OGL_ATT_LIST::GetAttributesList( aaMode ),
119 m_boardAdapter, m_currentCamera, Prj().Get3DCacheManager() );
120
121 LoadSettings( cfg );
122 loadCommonSettings();
123
124 SetUserViewports( Prj().GetProjectFile().m_Viewports3D );
125
126 // Create the manager
127 m_toolManager = new TOOL_MANAGER;
128 m_toolManager->SetEnvironment( GetBoard(), nullptr, nullptr, cfg, this );
129
130 m_actions = new EDA_3D_ACTIONS();
131 m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
132 m_canvas->SetEventDispatcher( m_toolDispatcher );
133
134 // Register tools
135 m_toolManager->RegisterTool( new COMMON_CONTROL );
136 m_toolManager->RegisterTool( new EDA_3D_CONTROLLER );
137 m_toolManager->InitTools();
138
139 setupUIConditions();
140
141 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
142 ctrlTool->SetRotationIncrement( cfg->m_Camera.rotation_increment );
143
144 // Run the viewer control tool, it is supposed to be always active
145 m_toolManager->InvokeTool( "3DViewer.Control" );
146
147 CreateMenuBar();
148 ReCreateMainToolbar();
149
150 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
151
152 m_auimgr.SetManagedWindow( this );
153
154 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( wxS( "MainToolbar" ) ).Top().Layer( 6 ) );
155 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ).Top().Layer( 1 ) );
156 m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) ).Center() );
157
158 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
159 // hiding it.
160 m_auimgr.Update();
161
162 // We don't want the infobar displayed right away
163 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
164 m_auimgr.Update();
165
166 m_canvas->SetInfoBar( m_infoBar );
167 m_canvas->SetStatusBar( status_bar );
168
169#if defined( KICAD_USE_3DCONNEXION )
170 try
171 {
172 m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas );
173 }
174 catch( const std::system_error& e )
175 {
176 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
177 }
178#endif
179
180 // Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
181 // in order to receive mouse events. Otherwise, the user has to click somewhere on
182 // the canvas before it will respond to mouse wheel events.
183 m_canvas->SetFocus();
184
185 m_cbViewports->Connect( wxEVT_COMMAND_CHOICE_SELECTED,
186 wxCommandEventHandler( EDA_3D_VIEWER_FRAME::onViewportChanged ),
187 nullptr, this );
188 m_cbViewports->Connect( wxEVT_UPDATE_UI,
189 wxUpdateUIEventHandler( EDA_3D_VIEWER_FRAME::onUpdateViewportsCb ),
190 nullptr, this );
191}
192
193
195{
196#if defined( KICAD_USE_3DCONNEXION )
197 if( m_spaceMouse != nullptr )
198 {
199 delete m_spaceMouse;
200 }
201#endif
202
204
205 m_cbViewports->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED,
206 wxCommandEventHandler( EDA_3D_VIEWER_FRAME::onViewportChanged ),
207 nullptr, this );
208 m_cbViewports->Disconnect( wxEVT_UPDATE_UI,
209 wxUpdateUIEventHandler( EDA_3D_VIEWER_FRAME::onUpdateViewportsCb ),
210 nullptr, this );
211
212 m_canvas->SetEventDispatcher( nullptr );
213
214 m_auimgr.UnInit();
215}
216
217
219{
221
224
225// Helper to define check conditions
226#define GridSizeCheck( x ) ACTION_CONDITIONS().Check( cond.GridSize( x ) )
227
228 auto raytracing =
229 [this]( const SELECTION& aSel )
230 {
232 };
233 auto showTH =
234 [this]( const SELECTION& aSel )
235 {
237 };
238 auto showSMD =
239 [this]( const SELECTION& aSel )
240 {
242 };
243 auto showVirtual =
244 [this]( const SELECTION& aSel )
245 {
247 };
248 auto show_NotInPosfile =
249 [this]( const SELECTION& aSel )
250 {
252 };
253 auto showBBoxes =
254 [this]( const SELECTION& aSel )
255 {
257 };
258 auto showAxes =
259 [this]( const SELECTION& aSel )
260 {
262 };
263 auto ortho =
264 [this]( const SELECTION& )
265 {
267 };
268
270
272 mgr->SetConditions( EDA_3D_ACTIONS::showSMD, ACTION_CONDITIONS().Check( showSMD ) );
273 mgr->SetConditions( EDA_3D_ACTIONS::showVirtual, ACTION_CONDITIONS().Check( showVirtual ) );
274 mgr->SetConditions( EDA_3D_ACTIONS::showNotInPosFile, ACTION_CONDITIONS().Check( show_NotInPosfile ) );
275
276
277 mgr->SetConditions( EDA_3D_ACTIONS::showBBoxes, ACTION_CONDITIONS().Check( showBBoxes ) );
278 mgr->SetConditions( EDA_3D_ACTIONS::showAxis, ACTION_CONDITIONS().Check( showAxes ) );
279
286
287#undef GridSizeCheck
288}
289
290
291bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent )
292{
293 static bool s_viewportSwitcherShown = false;
294
295 // wxWidgets generates no key events for the tab key when the ctrl key is held down. One
296 // way around this is to look at all events and inspect the keyboard state of the tab key.
297 // However, this runs into issues on some linux VMs where querying the keyboard state is
298 // very slow. Fortunately we only use ctrl-tab on Mac, so we implement this lovely hack:
299#ifdef __WXMAC__
300 if( wxGetKeyState( WXK_TAB ) )
301#else
302 if( ( aEvent.GetEventType() == wxEVT_CHAR || aEvent.GetEventType() == wxEVT_CHAR_HOOK )
303 && static_cast<wxKeyEvent&>( aEvent ).GetKeyCode() == WXK_TAB )
304#endif
305 {
306 if( !s_viewportSwitcherShown && wxGetKeyState( VIEWPORT_SWITCH_KEY ) )
307 {
308 if( this->IsActive() )
309 {
310 if( m_viewportMRU.size() > 0 )
311 {
313
314 s_viewportSwitcherShown = true;
315 switcher.ShowModal();
316 s_viewportSwitcherShown = false;
317
318 int idx = switcher.GetSelection();
319
320 if( idx >= 0 && idx < (int) m_viewportMRU.size() )
322
323 return true;
324 }
325 }
326 }
327 }
328
329 return wxFrame::TryBefore( aEvent );
330}
331
332
333void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
334{
336
337#if defined( KICAD_USE_3DCONNEXION )
338 if( m_spaceMouse != nullptr && aEvent.IsIconized() )
339 {
340 m_spaceMouse->SetFocus( false );
341 }
342#endif
343}
344
345
347{
348 // This will schedule a request to load later
349 if( m_canvas )
350 m_canvas->ReloadRequest( GetBoard(), Prj().Get3DCacheManager() );
351}
352
353
354void EDA_3D_VIEWER_FRAME::NewDisplay( bool aForceImmediateRedraw )
355{
357
358 // After the ReloadRequest call, the refresh often takes a bit of time,
359 // and it is made here only on request.
360 if( aForceImmediateRedraw )
361 m_canvas->Refresh();
362}
363
364
366{
367 // Only update in OpenGL for an interactive interaction
369 m_canvas->Request_refresh( true );
370}
371
372
374{
377 else
378 NewDisplay( true );
379}
380
381
382void EDA_3D_VIEWER_FRAME::Exit3DFrame( wxCommandEvent &event )
383{
384 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Exit3DFrame" ) );
385
386 Close( true );
387}
388
389
390void EDA_3D_VIEWER_FRAME::OnCloseWindow( wxCloseEvent &event )
391{
392 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnCloseWindow" ) );
393
394 if( m_canvas )
395 m_canvas->Close();
396
397 Destroy();
398 event.Skip( true );
399}
400
401
403{
404 int id = event.GetId();
405 bool isChecked = event.IsChecked();
406
407 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Process_Special_Functions id %d "
408 "isChecked %d" ),
409 id,
410 isChecked );
411
412 if( m_canvas == nullptr )
413 return;
414
415 switch( id )
416 {
418 NewDisplay( true );
419 break;
420
424 takeScreenshot( event );
425 return;
426
428 {
429 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
430 cfg->ResetToDefaults();
431 LoadSettings( cfg );
432
433 // Tell canvas that we (may have) changed the render engine
435
436 NewDisplay( true );
437 }
438 return;
439
440 default:
441 wxFAIL_MSG( wxT( "Invalid event in EDA_3D_VIEWER_FRAME::Process_Special_Functions()" ) );
442 return;
443 }
444}
445
446
447std::vector<VIEWPORT3D> EDA_3D_VIEWER_FRAME::GetUserViewports() const
448{
449 std::vector<VIEWPORT3D> ret;
450
451 for( const std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
452 ret.emplace_back( pair.second );
453
454 return ret;
455}
456
457
458void EDA_3D_VIEWER_FRAME::SetUserViewports( std::vector<VIEWPORT3D>& aViewportList )
459{
460 m_viewports.clear();
461
462 for( const VIEWPORT3D& viewport : aViewportList )
463 {
464 if( m_viewports.count( viewport.name ) )
465 continue;
466
467 m_viewports[viewport.name] = viewport;
468
469 m_viewportMRU.Add( viewport.name );
470 }
471}
472
473
474void EDA_3D_VIEWER_FRAME::applyViewport( const wxString& aViewportName )
475{
476 int idx = m_cbViewports->FindString( aViewportName );
477
478 if( idx >= 0 && idx < m_cbViewports->GetCount() - 3 /* separator */ )
479 {
480 m_cbViewports->SetSelection( idx );
481 m_lastSelectedViewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( idx ) );
482
484
487 else
489
490 if( !m_lastSelectedViewport->name.IsEmpty() )
491 {
494 }
495 }
496 else
497 {
498 m_cbViewports->SetSelection( -1 ); // separator
499 m_lastSelectedViewport = nullptr;
500 }
501}
502
503
504void EDA_3D_VIEWER_FRAME::onViewportChanged( wxCommandEvent& aEvent )
505{
506 int count = m_cbViewports->GetCount();
507 int index = m_cbViewports->GetSelection();
508
509 if( index >= 0 && index < count - 3 /* separator */ )
510 {
511 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
512
513 wxCHECK( viewport, /* void */ );
514
515 applyViewport( viewport->name );
516 }
517 else if( index == count - 2 )
518 {
519 // Save current state to new preset
520 wxString name;
521
522 wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name );
523
524 if( dlg.ShowModal() != wxID_OK )
525 {
527 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
528 else
529 m_cbViewports->SetSelection( -1 );
530
531 return;
532 }
533
534 name = dlg.GetValue();
535 bool exists = m_viewports.count( name );
536
537 if( !exists )
538 {
540
541 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
542 }
543 else
544 {
545 index = m_cbViewports->FindString( name );
547 m_viewportMRU.Remove( name );
548 }
549
550 m_cbViewports->SetSelection( index );
551 m_viewportMRU.Insert( name, 0 );
552
553 return;
554 }
555 else if( index == count - 1 )
556 {
557 // Delete an existing viewport
558 wxArrayString headers;
559 std::vector<wxArrayString> items;
560
561 headers.Add( _( "Viewports" ) );
562
563 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
564 {
565 wxArrayString item;
566 item.Add( pair.first );
567 items.emplace_back( item );
568 }
569
570 EDA_LIST_DIALOG dlg( this, _( "Delete Viewport" ), headers, items );
571 dlg.SetListLabel( _( "Select viewport:" ) );
572
573 if( dlg.ShowModal() == wxID_OK )
574 {
575 wxString viewportName = dlg.GetTextSelection();
576 int idx = m_cbViewports->FindString( viewportName );
577
578 if( idx != wxNOT_FOUND )
579 {
580 m_viewports.erase( viewportName );
581 m_cbViewports->Delete( idx );
582 m_viewportMRU.Remove( viewportName );
583 }
584 }
585
587 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
588 else
589 m_cbViewports->SetSelection( -1 );
590
591 return;
592 }
593
594 passOnFocus();
595}
596
597
598void EDA_3D_VIEWER_FRAME::onUpdateViewportsCb( wxUpdateUIEvent& aEvent )
599{
600 int count = m_cbViewports->GetCount();
601 int index = m_cbViewports->GetSelection();
602
603 if( index >= 0 && index < count - 3 )
604 {
605 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
606
607 wxCHECK( viewport, /* void */ );
608
609 if( m_currentCamera.GetViewMatrix() != viewport->matrix )
610 m_cbViewports->SetSelection( -1 );
611 }
612}
613
614
616{
618 RENDER_ENGINE old_engine = engine;
619
620 if( old_engine == RENDER_ENGINE::OPENGL )
622 else
623 engine = RENDER_ENGINE::OPENGL;
624
625 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ),
626 engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) );
627
628 if( old_engine != engine )
630}
631
632
633void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent )
634{
635 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ),
636 __WXFUNCTION__ );
637
640}
641
642
643void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent )
644{
645 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnActivate" ) );
646
647 if( aEvent.GetActive() && m_canvas )
648 {
649 // Reload data if 3D frame shows a board,
650 // because it can be changed since last frame activation
653
654 // Activates again the focus of the canvas so it will catch mouse and key events
655 m_canvas->SetFocus();
656 }
657
658#if defined( KICAD_USE_3DCONNEXION )
659 if( m_spaceMouse != nullptr )
660 {
661 m_spaceMouse->SetFocus( aEvent.GetActive() );
662 }
663#endif
664
665 aEvent.Skip(); // required under wxMAC
666}
667
668
669void EDA_3D_VIEWER_FRAME::OnSetFocus( wxFocusEvent& aEvent )
670{
671 // Activates again the focus of the canvas so it will catch mouse and key events
672 if( m_canvas )
673 m_canvas->SetFocus();
674
675 aEvent.Skip();
676}
677
678
680{
681 if( m_canvas )
682 m_canvas->SetFocus();
683}
684
685
687{
689
690 EDA_3D_VIEWER_SETTINGS* cfg = dynamic_cast<EDA_3D_VIEWER_SETTINGS*>( aCfg );
691 wxASSERT( cfg );
692
693 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::LoadSettings" ) );
694
695 if( cfg )
696 {
697 m_boardAdapter.m_Cfg = cfg;
698
699 // When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine
700 // because the ray tracing is very time consuming, and can be seen as not working
701 // (freeze window) with large boards.
703
707 }
708}
709
710
712{
713 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
714
716
717 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::SaveSettings" ) );
718
720 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting Ray Trace" )
721 :
722 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting OpenGL" ) );
723
724 if( cfg )
725 {
726 cfg->m_Camera.animation_enabled = m_canvas->GetAnimationEnabled();
727 cfg->m_Camera.moving_speed_multiplier = m_canvas->GetMovingSpeedMultiplier();
728 cfg->m_Camera.projection_mode = m_canvas->GetProjectionMode();
729
730 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
731 cfg->m_Camera.rotation_increment = ctrlTool->GetRotationIncrement();
732 }
733}
734
735
736void EDA_3D_VIEWER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
737{
738 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::CommonSettingsChanged" ) );
739
740 // Regen menu bars, etc
741 EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
742
743 // There is no base class that handles toolbars for this frame
745
747 LoadSettings( Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>() );
748
749 NewDisplay( true );
750}
751
752
753void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
754{
755 wxString fullFileName;
756 bool fmt_is_jpeg = false;
757
758 if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
759 fmt_is_jpeg = true;
760
761 if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
762 {
763 // Remember path between saves during this session only.
764 const wxString wildcard = fmt_is_jpeg ? JpegFileWildcard() : PngFileWildcard();
765 const wxString ext = fmt_is_jpeg ? JpegFileExtension : PngFileExtension;
766
767 // First time path is set to the project path.
770
772
773 wxFileDialog dlg( this, _( "3D Image File Name" ),
775 m_defaultSaveScreenshotFileName.GetFullName(), wildcard,
776 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
777
778 if( dlg.ShowModal() == wxID_CANCEL )
779 return;
780
781 m_defaultSaveScreenshotFileName = dlg.GetPath();
782
783 if( m_defaultSaveScreenshotFileName.GetExt().IsEmpty() )
785
786 fullFileName = m_defaultSaveScreenshotFileName.GetFullPath();
787
788 wxFileName fn = fullFileName;
789
790 if( !fn.IsDirWritable() )
791 {
792 wxString msg;
793
794 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fullFileName );
795 wxMessageBox( msg, _( "Error" ), wxOK | wxICON_ERROR, this );
796 return;
797 }
798
799 // Be sure the screen area destroyed by the file dialog is redrawn
800 // before making a screen copy.
801 // Without this call, under Linux the screen refresh is made to late.
802 wxYield();
803 }
804
805 // Be sure we have the latest 3D view (remember 3D view is buffered)
806 m_canvas->Request_refresh( true );
807 wxYield();
808
809 // Build image from the 3D buffer
810 wxWindowUpdateLocker noUpdates( this );
811
812 wxImage screenshotImage;
813
814 if( m_canvas )
815 m_canvas->GetScreenshot( screenshotImage );
816
817 if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
818 {
819 wxBitmap bitmap( screenshotImage );
820
821 wxLogNull doNotLog; // disable logging of failed clipboard actions
822
823 if( wxTheClipboard->Open() )
824 {
825 wxBitmapDataObject* dobjBmp = new wxBitmapDataObject( bitmap );
826
827 if( !wxTheClipboard->SetData( dobjBmp ) )
828 wxMessageBox( _( "Failed to copy image to clipboard" ) );
829
830 wxTheClipboard->Flush(); /* the data in clipboard will stay
831 * available after the application exits */
832 wxTheClipboard->Close();
833 }
834 }
835 else
836 {
837 if( !screenshotImage.SaveFile( fullFileName,
838 fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
839 wxMessageBox( _( "Can't save file" ) );
840
841 screenshotImage.Destroy();
842 }
843}
844
845
847{
848 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::RenderEngineChanged()" ) );
849
850 if( m_canvas )
852}
853
854
856{
857 wxCHECK_RET( m_canvas, wxT( "Cannot load settings to null canvas" ) );
858
859 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
860
861 const DPI_SCALING dpi{ settings, this };
862 m_canvas->SetScaleFactor( dpi.GetScaleFactor() );
863
864 // TODO(JE) use all control options
866}
RENDER_ENGINE
Render engine mode.
Definition: 3d_enums.h:64
@ ID_MENU_SCREENCOPY_PNG
Definition: 3d_viewer_id.h:31
@ ID_DISABLE_RAY_TRACING
Definition: 3d_viewer_id.h:42
@ ID_START_COMMAND_3D
Definition: 3d_viewer_id.h:19
@ ID_MENU_COMMAND_END
Definition: 3d_viewer_id.h:38
@ ID_RELOAD3D_BOARD
Definition: 3d_viewer_id.h:20
@ ID_TOOL_SCREENCOPY_TOCLIBBOARD
Definition: 3d_viewer_id.h:29
@ ID_MENU3D_RESET_DEFAULTS
Definition: 3d_viewer_id.h:35
@ ID_RENDER_CURRENT_VIEW
Definition: 3d_viewer_id.h:40
@ ID_MENU_SCREENCOPY_JPEG
Definition: 3d_viewer_id.h:32
const char * name
Definition: DXF_plotter.cpp:56
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:105
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:62
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...
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:110
EDA_3D_VIEWER_SETTINGS * m_Cfg
bool m_MousewheelPanning
PROJECTION_TYPE GetProjection()
Definition: camera.h:179
const glm::mat4 & GetViewMatrix() const
Definition: camera.cpp:450
void SetViewMatrix(glm::mat4 aViewMatrix)
Set the affine matrix to be applied to a transformation camera.
Definition: camera.cpp:456
Handle actions that are shared between different applications.
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
Definition: dpi_scaling.h:37
EDA_3D_ACTIONS.
static TOOL_ACTION showNotInPosFile
static TOOL_ACTION showTHT
static TOOL_ACTION noGrid
static TOOL_ACTION show2_5mmGrid
static TOOL_ACTION show1mmGrid
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 RenderRaytracingRequest()
Request to render the current view in Raytracing mode.
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 onViewportChanged(wxCommandEvent &aEvent)
PCB_BASE_FRAME * Parent() const
void SetUserViewports(std::vector< VIEWPORT3D > &aViewportList)
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 onUpdateViewportsCb(wxUpdateUIEvent &aEvent)
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 ReloadRequest()
Request reloading the 3D view.
wxFileName m_defaultSaveScreenshotFileName
VIEWPORT3D * m_lastSelectedViewport
void onRenderEngineSelection(wxCommandEvent &event)
std::map< wxString, VIEWPORT3D > m_viewports
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
NL_3D_VIEWER_PLUGIN * m_spaceMouse
void applyViewport(const wxString &aViewportName)
switch to a given predefined 3D viewport
void loadCommonSettings()
Load configuration from common settings.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification that common settings are updated.
std::vector< VIEWPORT3D > GetUserViewports() const
void handleIconizeEvent(wxIconizeEvent &aEvent) override
Handle a window iconize event.
virtual void handleIconizeEvent(wxIconizeEvent &aEvent)
Handle a window iconize event.
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.
A dialog which shows:
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
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 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:66
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:274
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 int * GetAttributesList(ANTIALIASING_MODE aAntiAliasingMode)
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:173
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:120
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:149
T * GetAppSettings(bool aLoadNow=true)
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:170
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
Master controller class:
Definition: tool_manager.h:55
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:196
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
#define QUALIFIED_VIEWER3D_FRAMENAME(parent)
#define VIEWPORT_SWITCH_KEY
@ FRAME_PCB_DISPLAY3D
Definition: frame_type.h:45
const std::string JpegFileExtension
const std::string PngFileExtension
wxString PngFileWildcard()
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:573
Declaration of the NL_3D_VIEWER_PLUGIN class.
ANTIALIASING_MODE
Anti-aliasing options.
Definition: ogl_attr_list.h:35
BOARD * GetBoard()
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
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.