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-2022 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/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, EDA_BASE_FRAME )
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 = _( "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( "MainToolbar" ).Top().Layer( 6 ) );
155 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( "InfoBar" ).Top().Layer( 1 ) );
156 m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( "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( "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 // On Windows, the Alt key is not usable, especially with TAB key
296 // Shift key is OK on all platforms
297 wxKeyCode viewSwitchKey = WXK_SHIFT;
298
299 if( aEvent.GetEventType() != wxEVT_CHAR && aEvent.GetEventType() != wxEVT_CHAR_HOOK )
300 return wxFrame::TryBefore( aEvent );
301
302 if( !s_viewportSwitcherShown && wxGetKeyState( viewSwitchKey ) && wxGetKeyState( WXK_TAB ) )
303 {
304 if( this->IsActive() )
305 {
306 if( m_viewportMRU.size() > 0 )
307 {
308 EDA_VIEW_SWITCHER switcher( this, m_viewportMRU, viewSwitchKey );
309
310 s_viewportSwitcherShown = true;
311 switcher.ShowModal();
312 s_viewportSwitcherShown = false;
313
314 int idx = switcher.GetSelection();
315
316 if( idx >= 0 && idx < (int) m_viewportMRU.size() )
318
319 return true;
320 }
321 }
322 }
323
324 return wxFrame::TryBefore( aEvent );
325}
326
327
328void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
329{
331
332#if defined( KICAD_USE_3DCONNEXION )
333 if( m_spaceMouse != nullptr && aEvent.IsIconized() )
334 {
335 m_spaceMouse->SetFocus( false );
336 }
337#endif
338}
339
340
342{
343 // This will schedule a request to load later
344 if( m_canvas )
345 m_canvas->ReloadRequest( GetBoard(), Prj().Get3DCacheManager() );
346}
347
348
349void EDA_3D_VIEWER_FRAME::NewDisplay( bool aForceImmediateRedraw )
350{
352
353 // After the ReloadRequest call, the refresh often takes a bit of time,
354 // and it is made here only on request.
355 if( aForceImmediateRedraw )
356 m_canvas->Refresh();
357}
358
359
361{
362 // Only update in OpenGL for an interactive interaction
364 m_canvas->Request_refresh( true );
365}
366
367
369{
372 else
373 NewDisplay( true );
374}
375
376
377void EDA_3D_VIEWER_FRAME::Exit3DFrame( wxCommandEvent &event )
378{
379 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Exit3DFrame" ) );
380
381 Close( true );
382}
383
384
385void EDA_3D_VIEWER_FRAME::OnCloseWindow( wxCloseEvent &event )
386{
387 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnCloseWindow" ) );
388
389 if( m_canvas )
390 m_canvas->Close();
391
392 Destroy();
393 event.Skip( true );
394}
395
396
398{
399 int id = event.GetId();
400 bool isChecked = event.IsChecked();
401
402 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Process_Special_Functions id %d "
403 "isChecked %d" ),
404 id,
405 isChecked );
406
407 if( m_canvas == nullptr )
408 return;
409
410 switch( id )
411 {
413 NewDisplay( true );
414 break;
415
419 takeScreenshot( event );
420 return;
421
423 {
424 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
425 cfg->ResetToDefaults();
426 LoadSettings( cfg );
427
428 // Tell canvas that we (may have) changed the render engine
430
431 NewDisplay( true );
432 }
433 return;
434
435 default:
436 wxFAIL_MSG( wxT( "Invalid event in EDA_3D_VIEWER_FRAME::Process_Special_Functions()" ) );
437 return;
438 }
439}
440
441
442std::vector<VIEWPORT3D> EDA_3D_VIEWER_FRAME::GetUserViewports() const
443{
444 std::vector<VIEWPORT3D> ret;
445
446 for( const std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
447 ret.emplace_back( pair.second );
448
449 return ret;
450}
451
452
453void EDA_3D_VIEWER_FRAME::SetUserViewports( std::vector<VIEWPORT3D>& aViewportList )
454{
455 m_viewports.clear();
456
457 for( const VIEWPORT3D& viewport : aViewportList )
458 {
459 if( m_viewports.count( viewport.name ) )
460 continue;
461
462 m_viewports[viewport.name] = viewport;
463
464 m_viewportMRU.Add( viewport.name );
465 }
466}
467
468
469void EDA_3D_VIEWER_FRAME::applyViewport( const wxString& aViewportName )
470{
471 int idx = m_cbViewports->FindString( aViewportName );
472
473 if( idx >= 0 && m_cbViewports->GetSelection() != idx )
474 {
475 m_cbViewports->SetSelection( idx );
476 m_lastSelectedViewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( idx ) );
477
479
482 else
484 }
485 else
486 {
487 m_cbViewports->SetSelection( -1 ); // separator
488 m_lastSelectedViewport = nullptr;
489 }
490}
491
492
493void EDA_3D_VIEWER_FRAME::onViewportChanged( wxCommandEvent& aEvent )
494{
495 int count = m_cbViewports->GetCount();
496 int index = m_cbViewports->GetSelection();
497
498 if( index >= 0 && index < count - 3 )
499 {
500 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
501
502 wxCHECK( viewport, /* void */ );
503
504 applyViewport( viewport->name );
505
506 if( !viewport->name.IsEmpty() )
507 {
508 m_viewportMRU.Remove( viewport->name );
509 m_viewportMRU.Insert( viewport->name, 0 );
510 }
511 }
512 else if( index == count - 2 )
513 {
514 // Save current state to new preset
515 wxString name;
516
517 wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name );
518
519 if( dlg.ShowModal() != wxID_OK )
520 {
522 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
523 else
524 m_cbViewports->SetSelection( -1 );
525
526 return;
527 }
528
529 name = dlg.GetValue();
530 bool exists = m_viewports.count( name );
531
532 if( !exists )
533 {
535
536 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
537 }
538 else
539 {
540 index = m_cbViewports->FindString( name );
541 m_viewportMRU.Remove( name );
542 }
543
544 m_cbViewports->SetSelection( index );
545 m_viewportMRU.Insert( name, 0 );
546
547 return;
548 }
549 else if( index == count - 1 )
550 {
551 // Delete an existing viewport
552 wxArrayString headers;
553 std::vector<wxArrayString> items;
554
555 headers.Add( _( "Viewports" ) );
556
557 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
558 {
559 wxArrayString item;
560 item.Add( pair.first );
561 items.emplace_back( item );
562 }
563
564 EDA_LIST_DIALOG dlg( this, _( "Delete Viewport" ), headers, items );
565 dlg.SetListLabel( _( "Select viewport:" ) );
566
567 if( dlg.ShowModal() == wxID_OK )
568 {
569 wxString viewportName = dlg.GetTextSelection();
570 int idx = m_cbViewports->FindString( viewportName );
571
572 if( idx != wxNOT_FOUND )
573 {
574 m_viewports.erase( viewportName );
575 m_cbViewports->Delete( idx );
576 m_viewportMRU.Remove( viewportName );
577 }
578 }
579
581 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
582 else
583 m_cbViewports->SetSelection( -1 );
584
585 return;
586 }
587
588 passOnFocus();
589}
590
591
592void EDA_3D_VIEWER_FRAME::onUpdateViewportsCb( wxUpdateUIEvent& aEvent )
593{
594 int count = m_cbViewports->GetCount();
595 int index = m_cbViewports->GetSelection();
596
597 if( index >= 0 && index < count - 3 )
598 {
599 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
600
601 wxCHECK( viewport, /* void */ );
602
603 if( m_currentCamera.GetViewMatrix() != viewport->matrix )
604 m_cbViewports->SetSelection( -1 );
605 }
606}
607
608
610{
612 RENDER_ENGINE old_engine = engine;
613
614 if( old_engine == RENDER_ENGINE::OPENGL )
616 else
617 engine = RENDER_ENGINE::OPENGL;
618
619 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ),
620 engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) );
621
622 if( old_engine != engine )
624}
625
626
627void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent )
628{
629 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ),
630 __WXFUNCTION__ );
631
634}
635
636
637void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent )
638{
639 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnActivate" ) );
640
641 if( aEvent.GetActive() && m_canvas )
642 {
643 // Reload data if 3D frame shows a board,
644 // because it can be changed since last frame activation
647
648 // Activates again the focus of the canvas so it will catch mouse and key events
649 m_canvas->SetFocus();
650 }
651
652#if defined( KICAD_USE_3DCONNEXION )
653 if( m_spaceMouse != nullptr )
654 {
655 m_spaceMouse->SetFocus( aEvent.GetActive() );
656 }
657#endif
658
659 aEvent.Skip(); // required under wxMAC
660}
661
662
663void EDA_3D_VIEWER_FRAME::OnSetFocus( wxFocusEvent& aEvent )
664{
665 // Activates again the focus of the canvas so it will catch mouse and key events
666 if( m_canvas )
667 m_canvas->SetFocus();
668
669 aEvent.Skip();
670}
671
672
674{
675 if( m_canvas )
676 m_canvas->SetFocus();
677}
678
679
681{
683
684 EDA_3D_VIEWER_SETTINGS* cfg = dynamic_cast<EDA_3D_VIEWER_SETTINGS*>( aCfg );
685 wxASSERT( cfg );
686
687 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::LoadSettings" ) );
688
689 if( cfg )
690 {
691 m_boardAdapter.m_Cfg = cfg;
692
693 // When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine
694 // because the ray tracing is very time consuming, and can be seen as not working
695 // (freeze window) with large boards.
697
701 }
702}
703
704
706{
707 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
708
710
711 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::SaveSettings" ) );
712
714 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting Ray Trace" )
715 :
716 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting OpenGL" ) );
717
718 if( cfg )
719 {
720 cfg->m_Camera.animation_enabled = m_canvas->GetAnimationEnabled();
721 cfg->m_Camera.moving_speed_multiplier = m_canvas->GetMovingSpeedMultiplier();
722 cfg->m_Camera.projection_mode = m_canvas->GetProjectionMode();
723
724 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
725 cfg->m_Camera.rotation_increment = ctrlTool->GetRotationIncrement();
726 }
727}
728
729
730void EDA_3D_VIEWER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
731{
732 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::CommonSettingsChanged" ) );
733
734 // Regen menu bars, etc
735 EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
736
737 // There is no base class that handles toolbars for this frame
739
741 LoadSettings( Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>() );
742
743 NewDisplay( true );
744}
745
746
747void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
748{
749 wxString fullFileName;
750 bool fmt_is_jpeg = false;
751
752 if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
753 fmt_is_jpeg = true;
754
755 if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
756 {
757 // Remember path between saves during this session only.
758 const wxString wildcard = fmt_is_jpeg ? JpegFileWildcard() : PngFileWildcard();
759 const wxString ext = fmt_is_jpeg ? JpegFileExtension : PngFileExtension;
760
761 // First time path is set to the project path.
764
766
767 wxFileDialog dlg( this, _( "3D Image File Name" ),
769 m_defaultSaveScreenshotFileName.GetFullName(), wildcard,
770 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
771
772 if( dlg.ShowModal() == wxID_CANCEL )
773 return;
774
775 m_defaultSaveScreenshotFileName = dlg.GetPath();
776
777 if( m_defaultSaveScreenshotFileName.GetExt().IsEmpty() )
779
780 fullFileName = m_defaultSaveScreenshotFileName.GetFullPath();
781
782 wxFileName fn = fullFileName;
783
784 if( !fn.IsDirWritable() )
785 {
786 wxString msg;
787
788 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fullFileName );
789 wxMessageBox( msg, _( "Error" ), wxOK | wxICON_ERROR, this );
790 return;
791 }
792
793 // Be sure the screen area destroyed by the file dialog is redrawn
794 // before making a screen copy.
795 // Without this call, under Linux the screen refresh is made to late.
796 wxYield();
797 }
798
799 // Be sure we have the latest 3D view (remember 3D view is buffered)
800 m_canvas->Request_refresh( true );
801 wxYield();
802
803 // Build image from the 3D buffer
804 wxWindowUpdateLocker noUpdates( this );
805
806 wxImage screenshotImage;
807
808 if( m_canvas )
809 m_canvas->GetScreenshot( screenshotImage );
810
811 if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
812 {
813 wxBitmap bitmap( screenshotImage );
814
815 wxLogNull doNotLog; // disable logging of failed clipboard actions
816
817 if( wxTheClipboard->Open() )
818 {
819 wxBitmapDataObject* dobjBmp = new wxBitmapDataObject( bitmap );
820
821 if( !wxTheClipboard->SetData( dobjBmp ) )
822 wxMessageBox( _( "Failed to copy image to clipboard" ) );
823
824 wxTheClipboard->Flush(); /* the data in clipboard will stay
825 * available after the application exits */
826 wxTheClipboard->Close();
827 }
828 }
829 else
830 {
831 if( !screenshotImage.SaveFile( fullFileName,
832 fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
833 wxMessageBox( _( "Can't save file" ) );
834
835 screenshotImage.Destroy();
836 }
837}
838
839
841{
842 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::RenderEngineChanged()" ) );
843
844 if( m_canvas )
846}
847
848
850{
851 wxCHECK_RET( m_canvas, wxT( "Cannot load settings to null canvas" ) );
852
853 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
854
855 const DPI_SCALING dpi{ settings, this };
856 m_canvas->SetScaleFactor( dpi.GetScaleFactor() );
857
858 // TODO(JE) use all control options
860}
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:101
EDA_3D_VIEWER_SETTINGS * m_Cfg
bool m_MousewheelPanning
PROJECTION_TYPE GetProjection()
Definition: camera.h:176
const glm::mat4 & GetViewMatrix() const
Definition: camera.cpp:451
void SetViewMatrix(glm::mat4 aViewMatrix)
Set the affine matrix to be applied to a transformation camera.
Definition: camera.cpp:457
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:37
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)
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.
The base frame for deriving all KiCad main window classes.
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:267
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:119
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:148
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: infobar.h:75
#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)
@ 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:403
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.