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) 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 <advanced_config.h>
43#include <bitmaps.h>
45#include <core/arraydim.h>
46#include <gal/dpi_scaling.h>
47#include <pgm_base.h>
48#include <project.h>
52#include <tool/action_manager.h>
53#include <tool/common_control.h>
54#include <tool/tool_manager.h>
56#include <tool/action_toolbar.h>
57#include <widgets/wx_infobar.h>
59
61
69const wxChar* EDA_3D_VIEWER_FRAME::m_logTrace = wxT( "KI_TRACE_EDA_3D_VIEWER" );
70
71
72BEGIN_EVENT_TABLE( EDA_3D_VIEWER_FRAME, KIWAY_PLAYER )
73
75 EVT_SET_FOCUS( EDA_3D_VIEWER_FRAME::OnSetFocus )
76
78 EDA_3D_VIEWER_FRAME::Process_Special_Functions )
79
80 EVT_MENU( wxID_CLOSE, EDA_3D_VIEWER_FRAME::Exit3DFrame )
81 EVT_MENU( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER_FRAME::onRenderEngineSelection )
82 EVT_MENU( ID_DISABLE_RAY_TRACING, EDA_3D_VIEWER_FRAME::onDisableRayTracing )
83
84 EVT_CLOSE( EDA_3D_VIEWER_FRAME::OnCloseWindow )
85END_EVENT_TABLE()
86
87
89 const wxString& aTitle, long style ) :
90 KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle, wxDefaultPosition,
91 wxDefaultSize, style, QUALIFIED_VIEWER3D_FRAMENAME( aParent ), unityScale ),
92 m_mainToolBar( nullptr ), m_canvas( nullptr ), m_currentCamera( m_trackBallCamera ),
93 m_viewportsLabel( nullptr ),
94 m_cbViewports( nullptr ),
95 m_trackBallCamera( 2 * RANGE_SCALE_3D ), m_spaceMouse( nullptr )
96{
97 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME %s" ), aTitle );
98
99 m_disable_ray_tracing = false;
100 m_aboutTitle = _HKI( "KiCad 3D Viewer" );
101
102 // Give it an icon
103 wxIcon icon;
104 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_3d ) );
105 SetIcon( icon );
106
107 // Create the status line
108 static const int status_dims[4] = { -1, 170, 130, 130 };
109
110 wxStatusBar *status_bar = CreateStatusBar( arrayDim( status_dims ) );
111 SetStatusWidths( arrayDim( status_dims ), status_dims );
112
113 SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
115 ANTIALIASING_MODE aaMode = static_cast<ANTIALIASING_MODE>( cfg->m_Render.opengl_AA_mode );
116
117 m_canvas = new EDA_3D_CANVAS( this, OGL_ATT_LIST::GetAttributesList( aaMode ),
118 m_boardAdapter, m_currentCamera, Prj().Get3DCacheManager() );
119
120 LoadSettings( cfg );
121 loadCommonSettings();
122
123 SetUserViewports( Prj().GetProjectFile().m_Viewports3D );
124
125 // Create the manager
126 m_toolManager = new TOOL_MANAGER;
127 m_toolManager->SetEnvironment( GetBoard(), nullptr, nullptr, cfg, this );
128
129 m_actions = new EDA_3D_ACTIONS();
130 m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
131 m_canvas->SetEventDispatcher( m_toolDispatcher );
132
133 // Register tools
134 m_toolManager->RegisterTool( new COMMON_CONTROL );
135 m_toolManager->RegisterTool( new EDA_3D_CONTROLLER );
136 m_toolManager->InitTools();
137
138 setupUIConditions();
139
140 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
141 ctrlTool->SetRotationIncrement( cfg->m_Camera.rotation_increment );
142
143 // Run the viewer control tool, it is supposed to be always active
144 m_toolManager->InvokeTool( "3DViewer.Control" );
145
146 CreateMenuBar();
147 ReCreateMainToolbar();
148
149 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
150
151 m_auimgr.SetManagedWindow( this );
152
153 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( wxS( "MainToolbar" ) ).Top().Layer( 6 ) );
154 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ).Top().Layer( 1 ) );
155 m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) ).Center() );
156
157 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
158 // hiding it.
159 m_auimgr.Update();
160
161 // We don't want the infobar displayed right away
162 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
163 m_auimgr.Update();
164
165 m_canvas->SetInfoBar( m_infoBar );
166 m_canvas->SetStatusBar( status_bar );
167
168
169 if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver )
170 {
171 try
172 {
173 m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas );
174 }
175 catch( const std::system_error& e )
176 {
177 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
178 }
179 }
180
181 // Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
182 // in order to receive mouse events. Otherwise, the user has to click somewhere on
183 // the canvas before it will respond to mouse wheel events.
184 m_canvas->SetFocus();
185
186 m_cbViewports->Connect( wxEVT_COMMAND_CHOICE_SELECTED,
187 wxCommandEventHandler( EDA_3D_VIEWER_FRAME::onViewportChanged ),
188 nullptr, this );
189 m_cbViewports->Connect( wxEVT_UPDATE_UI,
190 wxUpdateUIEventHandler( EDA_3D_VIEWER_FRAME::onUpdateViewportsCb ),
191 nullptr, this );
192}
193
194
196{
197 delete m_spaceMouse;
198
200
201 m_cbViewports->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED,
202 wxCommandEventHandler( EDA_3D_VIEWER_FRAME::onViewportChanged ),
203 nullptr, this );
204 m_cbViewports->Disconnect( wxEVT_UPDATE_UI,
205 wxUpdateUIEventHandler( EDA_3D_VIEWER_FRAME::onUpdateViewportsCb ),
206 nullptr, this );
207
208 m_canvas->SetEventDispatcher( nullptr );
209
210 m_auimgr.UnInit();
211}
212
213
215{
217
220
221// Helper to define check conditions
222#define GridSizeCheck( x ) ACTION_CONDITIONS().Check( cond.GridSize( x ) )
223
224 auto raytracing =
225 [this]( const SELECTION& aSel )
226 {
227 return m_boardAdapter.m_Cfg->m_Render.engine != RENDER_ENGINE::OPENGL;
228 };
229 auto showTH =
230 [this]( const SELECTION& aSel )
231 {
233 };
234 auto showSMD =
235 [this]( const SELECTION& aSel )
236 {
238 };
239 auto showVirtual =
240 [this]( const SELECTION& aSel )
241 {
243 };
244 auto show_NotInPosfile =
245 [this]( const SELECTION& aSel )
246 {
248 };
249 auto show_DNP =
250 [this]( const SELECTION& aSel )
251 {
253 };
254 auto showBBoxes =
255 [this]( const SELECTION& aSel )
256 {
258 };
259 auto showAxes =
260 [this]( const SELECTION& aSel )
261 {
263 };
264 auto ortho =
265 [this]( const SELECTION& )
266 {
267 return m_currentCamera.GetProjection() == PROJECTION_TYPE::ORTHO;
268 };
269
271
273 mgr->SetConditions( EDA_3D_ACTIONS::showSMD, ACTION_CONDITIONS().Check( showSMD ) );
274 mgr->SetConditions( EDA_3D_ACTIONS::showVirtual, ACTION_CONDITIONS().Check( showVirtual ) );
275 mgr->SetConditions( EDA_3D_ACTIONS::showNotInPosFile, ACTION_CONDITIONS().Check( show_NotInPosfile ) );
276 mgr->SetConditions( EDA_3D_ACTIONS::showDNP, ACTION_CONDITIONS().Check( show_DNP ) );
277
278
279 mgr->SetConditions( EDA_3D_ACTIONS::showBBoxes, ACTION_CONDITIONS().Check( showBBoxes ) );
280 mgr->SetConditions( EDA_3D_ACTIONS::showAxis, ACTION_CONDITIONS().Check( showAxes ) );
281
282 mgr->SetConditions( EDA_3D_ACTIONS::noGrid, GridSizeCheck( GRID3D_TYPE::NONE ) );
283 mgr->SetConditions( EDA_3D_ACTIONS::show10mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_10MM ) );
284 mgr->SetConditions( EDA_3D_ACTIONS::show5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_5MM ) );
285 mgr->SetConditions( EDA_3D_ACTIONS::show2_5mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_2P5MM ) );
286 mgr->SetConditions( EDA_3D_ACTIONS::show1mmGrid, GridSizeCheck( GRID3D_TYPE::GRID_1MM ) );
288
289#undef GridSizeCheck
290}
291
292
293bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent )
294{
295 static bool s_viewportSwitcherShown = false;
296
297 // wxWidgets generates no key events for the tab key when the ctrl key is held down. One
298 // way around this is to look at all events and inspect the keyboard state of the tab key.
299 // However, this runs into issues on some linux VMs where querying the keyboard state is
300 // very slow. Fortunately we only use ctrl-tab on Mac, so we implement this lovely hack:
301#ifdef __WXMAC__
302 if( wxGetKeyState( WXK_TAB ) )
303#else
304 if( ( aEvent.GetEventType() == wxEVT_CHAR || aEvent.GetEventType() == wxEVT_CHAR_HOOK )
305 && static_cast<wxKeyEvent&>( aEvent ).GetKeyCode() == WXK_TAB )
306#endif
307 {
308 if( !s_viewportSwitcherShown && wxGetKeyState( VIEWPORT_SWITCH_KEY ) )
309 {
310 if( this->IsActive() )
311 {
312 if( m_viewportMRU.size() > 0 )
313 {
315
316 s_viewportSwitcherShown = true;
317 switcher.ShowModal();
318 s_viewportSwitcherShown = false;
319
320 int idx = switcher.GetSelection();
321
322 if( idx >= 0 && idx < (int) m_viewportMRU.size() )
324
325 return true;
326 }
327 }
328 }
329 }
330
331 return wxFrame::TryBefore( aEvent );
332}
333
334
335void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
336{
338
339 if( m_spaceMouse != nullptr && aEvent.IsIconized()
341 {
342 m_spaceMouse->SetFocus( false );
343 }
344}
345
346
348{
349 // This will schedule a request to load later
350 if( m_canvas )
351 m_canvas->ReloadRequest( GetBoard(), Prj().Get3DCacheManager() );
352}
353
354
355void EDA_3D_VIEWER_FRAME::NewDisplay( bool aForceImmediateRedraw )
356{
358
359 // After the ReloadRequest call, the refresh often takes a bit of time,
360 // and it is made here only on request.
361 if( aForceImmediateRedraw )
362 m_canvas->Refresh();
363}
364
365
367{
368 // Only update in OpenGL for an interactive interaction
369 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
370 m_canvas->Request_refresh( true );
371}
372
373
375{
376 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
378 else
379 NewDisplay( true );
380}
381
382
383void EDA_3D_VIEWER_FRAME::Exit3DFrame( wxCommandEvent &event )
384{
385 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Exit3DFrame" ) );
386
387 Close( true );
388}
389
390
391void EDA_3D_VIEWER_FRAME::OnCloseWindow( wxCloseEvent &event )
392{
393 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnCloseWindow" ) );
394
395 if( m_canvas )
396 m_canvas->Close();
397
398 Destroy();
399 event.Skip( true );
400}
401
402
404{
405 int id = event.GetId();
406 bool isChecked = event.IsChecked();
407
408 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::Process_Special_Functions id %d "
409 "isChecked %d" ),
410 id,
411 isChecked );
412
413 if( m_canvas == nullptr )
414 return;
415
416 switch( id )
417 {
419 NewDisplay( true );
420 break;
421
425 takeScreenshot( event );
426 return;
427
429 {
430 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
431 cfg->ResetToDefaults();
432 LoadSettings( cfg );
433
434 // Tell canvas that we (may have) changed the render engine
436
437 NewDisplay( true );
438 }
439 return;
440
441 default:
442 wxFAIL_MSG( wxT( "Invalid event in EDA_3D_VIEWER_FRAME::Process_Special_Functions()" ) );
443 return;
444 }
445}
446
447
448std::vector<VIEWPORT3D> EDA_3D_VIEWER_FRAME::GetUserViewports() const
449{
450 std::vector<VIEWPORT3D> ret;
451
452 for( const std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
453 ret.emplace_back( pair.second );
454
455 return ret;
456}
457
458
459void EDA_3D_VIEWER_FRAME::SetUserViewports( std::vector<VIEWPORT3D>& aViewportList )
460{
461 m_viewports.clear();
462
463 for( const VIEWPORT3D& viewport : aViewportList )
464 {
465 if( m_viewports.count( viewport.name ) )
466 continue;
467
468 m_viewports[viewport.name] = viewport;
469
470 m_viewportMRU.Add( viewport.name );
471 }
472}
473
474
475void EDA_3D_VIEWER_FRAME::applyViewport( const wxString& aViewportName )
476{
477 int idx = m_cbViewports->FindString( aViewportName );
478
479 if( idx >= 0 && idx < m_cbViewports->GetCount() - 3 /* separator */ )
480 {
481 m_cbViewports->SetSelection( idx );
482 m_lastSelectedViewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( idx ) );
483
485
486 if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
488 else
490
491 if( !m_lastSelectedViewport->name.IsEmpty() )
492 {
495 }
496 }
497 else
498 {
499 m_cbViewports->SetSelection( -1 ); // separator
500 m_lastSelectedViewport = nullptr;
501 }
502}
503
504
505void EDA_3D_VIEWER_FRAME::onViewportChanged( wxCommandEvent& aEvent )
506{
507 int count = m_cbViewports->GetCount();
508 int index = m_cbViewports->GetSelection();
509
510 if( index >= 0 && index < count - 3 /* separator */ )
511 {
512 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
513
514 wxCHECK( viewport, /* void */ );
515
516 applyViewport( viewport->name );
517 }
518 else if( index == count - 2 )
519 {
520 // Save current state to new preset
521 wxString name;
522
523 wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name );
524
525 if( dlg.ShowModal() != wxID_OK )
526 {
528 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
529 else
530 m_cbViewports->SetSelection( -1 );
531
532 return;
533 }
534
535 name = dlg.GetValue();
536 bool exists = m_viewports.count( name );
537
538 if( !exists )
539 {
541
542 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
543 }
544 else
545 {
546 index = m_cbViewports->FindString( name );
548 m_viewportMRU.Remove( name );
549 }
550
551 m_cbViewports->SetSelection( index );
552 m_viewportMRU.Insert( name, 0 );
553
554 return;
555 }
556 else if( index == count - 1 )
557 {
558 // Delete an existing viewport
559 wxArrayString headers;
560 std::vector<wxArrayString> items;
561
562 headers.Add( _( "Viewports" ) );
563
564 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
565 {
566 wxArrayString item;
567 item.Add( pair.first );
568 items.emplace_back( item );
569 }
570
571 EDA_LIST_DIALOG dlg( this, _( "Delete Viewport" ), headers, items );
572 dlg.SetListLabel( _( "Select viewport:" ) );
573
574 if( dlg.ShowModal() == wxID_OK )
575 {
576 wxString viewportName = dlg.GetTextSelection();
577 int idx = m_cbViewports->FindString( viewportName );
578
579 if( idx != wxNOT_FOUND )
580 {
581 m_viewports.erase( viewportName );
582 m_cbViewports->Delete( idx );
583 m_viewportMRU.Remove( viewportName );
584 }
585 }
586
588 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
589 else
590 m_cbViewports->SetSelection( -1 );
591
592 return;
593 }
594
595 passOnFocus();
596}
597
598
599void EDA_3D_VIEWER_FRAME::onUpdateViewportsCb( wxUpdateUIEvent& aEvent )
600{
601 int count = m_cbViewports->GetCount();
602 int index = m_cbViewports->GetSelection();
603
604 if( index >= 0 && index < count - 3 )
605 {
606 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
607
608 wxCHECK( viewport, /* void */ );
609
610 if( m_currentCamera.GetViewMatrix() != viewport->matrix )
611 m_cbViewports->SetSelection( -1 );
612 }
613}
614
615
617{
619 RENDER_ENGINE old_engine = engine;
620
621 if( old_engine == RENDER_ENGINE::OPENGL )
622 engine = RENDER_ENGINE::RAYTRACING;
623 else
624 engine = RENDER_ENGINE::OPENGL;
625
626 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ),
627 engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) );
628
629 if( old_engine != engine )
631}
632
633
634void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent )
635{
636 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ),
637 __WXFUNCTION__ );
638
640 m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
641}
642
643
644void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent )
645{
646 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnActivate" ) );
647
648 if( aEvent.GetActive() && m_canvas )
649 {
650 // Reload data if 3D frame shows a board,
651 // because it can be changed since last frame activation
654
655 // Activates again the focus of the canvas so it will catch mouse and key events
656 m_canvas->SetFocus();
657 }
658
659 if( m_spaceMouse != nullptr && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver )
660 m_spaceMouse->SetFocus( aEvent.GetActive() );
661
662 aEvent.Skip(); // required under wxMAC
663}
664
665
666void EDA_3D_VIEWER_FRAME::OnSetFocus( wxFocusEvent& aEvent )
667{
668 // Activates again the focus of the canvas so it will catch mouse and key events
669 if( m_canvas )
670 m_canvas->SetFocus();
671
672 aEvent.Skip();
673}
674
675
677{
678 if( m_canvas )
679 m_canvas->SetFocus();
680}
681
682
684{
686
687 EDA_3D_VIEWER_SETTINGS* cfg = dynamic_cast<EDA_3D_VIEWER_SETTINGS*>( aCfg );
688 wxASSERT( cfg );
689
690 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::LoadSettings" ) );
691
692 if( cfg )
693 {
694 m_boardAdapter.m_Cfg = cfg;
695
696 // When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine
697 // because the ray tracing is very time consuming, and can be seen as not working
698 // (freeze window) with large boards.
699 m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
700
704 }
705}
706
707
709{
710 auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
711
713
714 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::SaveSettings" ) );
715
716 wxLogTrace( m_logTrace, m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::RAYTRACING ?
717 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting Ray Trace" )
718 :
719 wxT( "EDA_3D_VIEWER_FRAME::SaveSettings render setting OpenGL" ) );
720
721 if( cfg )
722 {
723 cfg->m_Camera.animation_enabled = m_canvas->GetAnimationEnabled();
724 cfg->m_Camera.moving_speed_multiplier = m_canvas->GetMovingSpeedMultiplier();
725 cfg->m_Camera.projection_mode = m_canvas->GetProjectionMode();
726
727 if( EDA_3D_CONTROLLER* ctrlTool = GetToolManager()->GetTool<EDA_3D_CONTROLLER>() )
728 cfg->m_Camera.rotation_increment = ctrlTool->GetRotationIncrement();
729 }
730}
731
732
733void EDA_3D_VIEWER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
734{
735 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::CommonSettingsChanged" ) );
736
737 // Regen menu bars, etc
738 EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
739
740 // There is no base class that handles toolbars for this frame
742
744 LoadSettings( Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>() );
745
746 NewDisplay( true );
747}
748
749
750void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
751{
752 wxString fullFileName;
753 bool fmt_is_jpeg = false;
754
755 if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
756 fmt_is_jpeg = true;
757
758 if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
759 {
760 // Remember path between saves during this session only.
761 const wxString wildcard = fmt_is_jpeg ? JpegFileWildcard() : PngFileWildcard();
762 const wxString ext = fmt_is_jpeg ? JpegFileExtension : PngFileExtension;
763
764 // First time path is set to the project path.
767
769
770 wxFileDialog dlg( this, _( "3D Image File Name" ),
772 m_defaultSaveScreenshotFileName.GetFullName(), wildcard,
773 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
774
775 if( dlg.ShowModal() == wxID_CANCEL )
776 return;
777
778 m_defaultSaveScreenshotFileName = dlg.GetPath();
779
780 if( m_defaultSaveScreenshotFileName.GetExt().IsEmpty() )
782
783 fullFileName = m_defaultSaveScreenshotFileName.GetFullPath();
784
785 wxFileName fn = fullFileName;
786
787 if( !fn.IsDirWritable() )
788 {
789 wxString msg;
790
791 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fullFileName );
792 wxMessageBox( msg, _( "Error" ), wxOK | wxICON_ERROR, this );
793 return;
794 }
795
796 // Be sure the screen area destroyed by the file dialog is redrawn
797 // before making a screen copy.
798 // Without this call, under Linux the screen refresh is made to late.
799 wxYield();
800 }
801
802 // Be sure we have the latest 3D view (remember 3D view is buffered)
803 m_canvas->Request_refresh( true );
804 wxYield();
805
806 // Build image from the 3D buffer
807 wxWindowUpdateLocker noUpdates( this );
808
809 wxImage screenshotImage;
810
811 if( m_canvas )
812 m_canvas->GetScreenshot( screenshotImage );
813
814 if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
815 {
816 wxBitmap bitmap( screenshotImage );
817
818 wxLogNull doNotLog; // disable logging of failed clipboard actions
819
820 if( wxTheClipboard->Open() )
821 {
822 wxBitmapDataObject* dobjBmp = new wxBitmapDataObject( bitmap );
823
824 if( !wxTheClipboard->SetData( dobjBmp ) )
825 wxMessageBox( _( "Failed to copy image to clipboard" ) );
826
827 wxTheClipboard->Flush(); /* the data in clipboard will stay
828 * available after the application exits */
829 wxTheClipboard->Close();
830 }
831 }
832 else
833 {
834 if( !screenshotImage.SaveFile( fullFileName,
835 fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
836 wxMessageBox( _( "Can't save file" ) );
837
838 screenshotImage.Destroy();
839 }
840}
841
842
844{
845 wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::RenderEngineChanged()" ) );
846
847 if( m_canvas )
849}
850
851
853{
854 wxCHECK_RET( m_canvas, wxT( "Cannot load settings to null canvas" ) );
855
856 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
857
858 const DPI_SCALING dpi{ settings, this };
859 m_canvas->SetScaleFactor( dpi.GetScaleFactor() );
860
861 // TODO(JE) use all control options
863}
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:106
#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...
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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 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 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: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 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()
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
Declaration of the eda_3d_viewer class.
#define QUALIFIED_VIEWER3D_FRAMENAME(parent)
#define VIEWPORT_SWITCH_KEY
@ FRAME_PCB_DISPLAY3D
Definition: frame_type.h:45
bool m_Use3DConnexionDriver
Use the 3DConnexion Driver.
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:554
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:115
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.