KiCad PCB EDA Suite
Loading...
Searching...
No Matches
appearance_controls_3D.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) 2023 CERN
5 * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
22
23#include <bitmaps.h>
24#include <confirm.h>
25#include <pgm_base.h>
26#include <dpi_scaling_common.h>
27#include <eda_list_dialog.h>
28#include <pcb_display_options.h>
29#include <eda_3d_viewer_frame.h>
30#include <pcbnew_settings.h>
31#include <project.h>
34#include <tool/tool_manager.h>
35#include <tools/pcb_actions.h>
41#include <wx/bmpbuttn.h>
42#include <wx/sizer.h>
43#include <wx/textdlg.h>
44
45#include <../3d_rendering/opengl/render_3d_opengl.h>
46
47
48#define RR APPEARANCE_CONTROLS_3D::APPEARANCE_SETTING_3D // Render Row abbreviation to reduce source width
49
52
53 // text id tooltip
54 RR( _HKI( "Board Body" ), LAYER_3D_BOARD, _HKI( "Show board body" ) ),
55 RR( _HKI( "F.Cu" ), LAYER_3D_COPPER_TOP, _HKI( "Show front copper / surface finish color" ) ),
56 RR( _HKI( "B.Cu" ), LAYER_3D_COPPER_BOTTOM, _HKI( "Show back copper / surface finish color" ) ),
57 RR( _HKI( "Adhesive" ), LAYER_3D_ADHESIVE, _HKI( "Show adhesive" ) ),
58 RR( _HKI( "Solder Paste" ), LAYER_3D_SOLDERPASTE, _HKI( "Show solder paste" ) ),
59 RR( _HKI( "F.Silkscreen" ), LAYER_3D_SILKSCREEN_TOP, _HKI( "Show front silkscreen" ) ),
60 RR( _HKI( "B.Silkscreen" ), LAYER_3D_SILKSCREEN_BOTTOM, _HKI( "Show back silkscreen" ) ),
61 RR( _HKI( "F.Mask" ), LAYER_3D_SOLDERMASK_TOP, _HKI( "Show front solder mask" ) ),
62 RR( _HKI( "B.Mask" ), LAYER_3D_SOLDERMASK_BOTTOM, _HKI( "Show back solder mask" ) ),
63 RR( _HKI( "User.Drawings" ), LAYER_3D_USER_DRAWINGS, _HKI( "Show user drawings layer" ) ),
64 RR( _HKI( "User.Comments" ), LAYER_3D_USER_COMMENTS, _HKI( "Show user comments layer" ) ),
65 RR( _HKI( "User.Eco1" ), LAYER_3D_USER_ECO1, _HKI( "Show user ECO1 layer" ) ),
66 RR( _HKI( "User.Eco2" ), LAYER_3D_USER_ECO2, _HKI( "Show user ECO2 layer" ) ),
67 RR(),
68 RR( _HKI( "Through-hole Models" ), LAYER_3D_TH_MODELS, EDA_3D_ACTIONS::showTHT ),
73 RR( _HKI( "Model Bounding Boxes" ), LAYER_3D_BOUNDING_BOXES, EDA_3D_ACTIONS::showBBoxes ),
74 RR(),
75 RR( _HKI( "Values" ), LAYER_FP_VALUES, _HKI( "Show footprint values" ) ),
76 RR( _HKI( "References" ), LAYER_FP_REFERENCES, _HKI( "Show footprint references" ) ),
77 RR( _HKI( "Footprint Text" ), LAYER_FP_TEXT, _HKI( "Show all footprint text" ) ),
78 RR( _HKI( "Off-board Silkscreen" ), LAYER_3D_OFF_BOARD_SILK, _HKI( "Do not clip silk layers to board outline" ) ),
79 RR(),
81 RR( _HKI( "Background Start" ), LAYER_3D_BACKGROUND_TOP, _HKI( "Background gradient start color" ) ),
82 RR( _HKI( "Background End" ), LAYER_3D_BACKGROUND_BOTTOM, _HKI( "Background gradient end color" ) ),
83};
84
85
87 wxWindow* aFocusOwner ) :
89 m_frame( aParent ),
90 m_focusOwner( aFocusOwner ),
91 m_lastSelectedViewport( nullptr )
92{
93 DPI_SCALING_COMMON dpi( nullptr, m_frame );
94
95 int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x / dpi.GetContentScaleFactor();
96 int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
97 m_pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
98
99 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
100 SetBorders( true, false, false, false );
101
102 m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
104 m_windowLayers->SetScrollRate( 0, 5 );
105 m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS_3D::OnSetFocus, this );
106
107 m_envOuterSizer = new wxBoxSizer( wxVERTICAL );
108
109 wxFont infoFont = KIUI::GetInfoFont( this );
110 m_panelLayers->SetFont( infoFont );
111 m_windowLayers->SetFont( infoFont );
112 m_presetsLabel->SetFont( infoFont );
113 m_viewportsLabel->SetFont( infoFont );
114
115 m_cbLayerPresets->SetToolTip( wxString::Format( _( "Save and restore color and visibility "
116 "combinations.\n"
117 "Use %s+Tab to activate selector.\n"
118 "Successive Tabs while holding %s down will "
119 "cycle through presets in the popup." ),
122
123 m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore camera position and zoom.\n"
124 "Use %s+Tab to activate selector.\n"
125 "Successive Tabs while holding %s down will "
126 "cycle through viewports in the popup." ),
129
130 if( screenHeight <= 900 && m_pointSize >= indicatorSize )
131 m_pointSize = m_pointSize * 8 / 10;
132
134
135 m_toggleGridRenderer = new GRID_BITMAP_TOGGLE_RENDERER( KiBitmap( BITMAPS::visibility ),
136 KiBitmap( BITMAPS::visibility_off ) );
137}
138
139
141{
142}
143
144
146{
147 DPI_SCALING_COMMON dpi( nullptr, m_frame );
148 wxSize size( 220 * dpi.GetScaleFactor(), 480 * dpi.GetScaleFactor() );
149 return size;
150}
151
152
153void APPEARANCE_CONTROLS_3D::OnSetFocus( wxFocusEvent& aEvent )
154{
155#ifdef __WXMSW__
156 // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
157 // focus and give it back to the parent in the button event handler.
158 if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
159 {
160 wxCommandEvent evt( wxEVT_BUTTON );
161 wxPostEvent( btn, evt );
162 }
163#endif
164
165 passOnFocus();
166 aEvent.Skip();
167}
168
169
170void APPEARANCE_CONTROLS_3D::OnSize( wxSizeEvent& aEvent )
171{
172 aEvent.Skip();
173}
174
175
177{
178 Freeze();
182
183 Thaw();
184 Refresh();
185}
186
187
189{
190 // This is essentially a list of hacks because DarkMode isn't yet implemented inside
191 // wxWidgets.
192 //
193 // The individual wxPanels, COLOR_SWATCHes and GRID_CELL_COLOR_RENDERERs should really be
194 // overriding some virtual method or responding to some wxWidgets event so that the parent
195 // doesn't have to know what it contains. But, that's not where we are, so... :shrug:
196
197 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
198
199 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
200
201 for( wxSizerItem* child : m_layersOuterSizer->GetChildren() )
202 {
203 if( child && child->GetWindow() )
204 child->GetWindow()->SetBackgroundColour( m_layerPanelColour );
205 }
206}
207
208
210{
212}
213
214
215void APPEARANCE_CONTROLS_3D::ApplyLayerPreset( const wxString& aPresetName )
216{
217 if( aPresetName == FOLLOW_PCB || aPresetName == FOLLOW_PLOT_SETTINGS )
218 {
219 m_frame->GetAdapter().m_Cfg->m_CurrentPreset = aPresetName;
221 m_frame->NewDisplay( true );
222 }
223 else if( LAYER_PRESET_3D* preset = m_frame->GetAdapter().m_Cfg->FindPreset( aPresetName ) )
224 {
225 doApplyLayerPreset( *preset );
226 }
227
228 // Move to front of MRU list
229 if( m_presetMRU.Index( aPresetName ) != wxNOT_FOUND )
230 m_presetMRU.Remove( aPresetName );
231
232 m_presetMRU.Insert( aPresetName, 0 );
233
234 updateLayerPresetWidget( aPresetName );
235}
236
237
238std::vector<VIEWPORT3D> APPEARANCE_CONTROLS_3D::GetUserViewports() const
239{
240 std::vector<VIEWPORT3D> ret;
241
242 for( const auto& [name, viewport] : m_viewports )
243 ret.emplace_back( viewport );
244
245 return ret;
246}
247
248
249void APPEARANCE_CONTROLS_3D::SetUserViewports( std::vector<VIEWPORT3D>& aViewportList )
250{
251 m_viewports.clear();
252
253 for( const VIEWPORT3D& viewport : aViewportList )
254 {
255 if( m_viewports.count( viewport.name ) )
256 continue;
257
258 m_viewports[viewport.name] = viewport;
259
260 m_viewportMRU.Add( viewport.name );
261 }
262
264
265 // Now is as good a time as any to initialize the layer presets as well.
267
268 m_presetMRU.Add( FOLLOW_PCB );
270
271 for( const LAYER_PRESET_3D& preset : m_frame->GetAdapter().m_Cfg->m_LayerPresets )
272 m_presetMRU.Add( preset.name );
273}
274
275
276void APPEARANCE_CONTROLS_3D::ApplyViewport( const wxString& aViewportName )
277{
278 int idx = m_cbViewports->FindString( aViewportName );
279
280 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
281 {
282 m_cbViewports->SetSelection( idx );
283 m_lastSelectedViewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( idx ) );
284 }
285 else
286 {
287 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
288 m_lastSelectedViewport = nullptr;
289 }
290
293}
294
295
296void APPEARANCE_CONTROLS_3D::OnLayerVisibilityChanged( int aLayer, bool isVisible )
297{
298 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
299 const std::map<int, COLOR4D>& colors = m_frame->GetAdapter().GetLayerColors();
300 bool killFollow = false;
301 bool doFastRefresh = false; // true to just refresh the display
302
303 // Special-case controls
304 switch( aLayer )
305 {
306 case LAYER_FP_TEXT:
307 // Because Footprint Text is a meta-control that also can disable values/references,
308 // drag them along here so that the user is less likely to be confused.
309 if( !isVisible )
310 {
311 visibleLayers.set( LAYER_FP_REFERENCES, false );
312 visibleLayers.set( LAYER_FP_VALUES, false );
313 }
314
315 visibleLayers.set( LAYER_FP_TEXT, isVisible );
316 killFollow = true;
317 break;
318
320 case LAYER_FP_VALUES:
321 // In case that user changes Footprint Value/References when the Footprint Text
322 // meta-control is disabled, we should put it back on.
323 if( isVisible )
324 visibleLayers.set( LAYER_FP_TEXT, true );
325
326 visibleLayers.set( aLayer, isVisible );
327 killFollow = true;
328 break;
329
330 case LAYER_3D_BOARD:
343 visibleLayers.set( aLayer, isVisible );
344 killFollow = true;
345 break;
346
352 doFastRefresh = true;
353 visibleLayers.set( aLayer, isVisible );
354 break;
355
356 default:
357 visibleLayers.set( aLayer, isVisible );
358 break;
359 }
360
361 m_frame->GetAdapter().SetVisibleLayers( visibleLayers );
362 m_frame->GetAdapter().SetLayerColors( colors );
363
364 const wxString& currentPreset = m_frame->GetAdapter().m_Cfg->m_CurrentPreset;
365
366 if( ( currentPreset != FOLLOW_PCB && currentPreset != FOLLOW_PLOT_SETTINGS ) || killFollow )
368
370
371 if( doFastRefresh && m_frame->GetAdapter().m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
372 {
373 RENDER_3D_OPENGL* renderer =
374 static_cast<RENDER_3D_OPENGL*>( m_frame->GetCanvas()->GetCurrentRender() );
375 renderer->Load3dModelsIfNeeded();
377 }
378 else
379 {
380 m_frame->NewDisplay( true );
381 }
382}
383
384
386{
387 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
388 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
389
390 m_frame->GetAdapter().SetVisibleLayers( visibleLayers );
391 m_frame->GetAdapter().SetLayerColors( colors );
392
393 int layer = aSwatch->GetId();
394 COLOR4D newColor = aSwatch->GetSwatchColor();
395
396 colors[ layer ] = newColor;
397
398 if( layer == LAYER_3D_COPPER_TOP )
399 colors[ LAYER_3D_COPPER_BOTTOM ] = newColor;
400 else if( layer == LAYER_3D_COPPER_BOTTOM )
401 colors[ LAYER_3D_COPPER_TOP ] = newColor;
402
403 m_frame->GetAdapter().SetLayerColors( colors );
404
406
407 m_frame->NewDisplay( true );
408}
409
410
412{
413 int swatchWidth = m_windowLayers->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
414
415 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
416 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
417 std::map<int, COLOR4D> defaultColors = m_frame->GetAdapter().GetDefaultColors();
418
419 m_layerSettings.clear();
420 m_layersOuterSizer->Clear( true );
421 m_layersOuterSizer->AddSpacer( 5 );
422
423 m_envOuterSizer->Clear( true );
424
425 auto appendLayer =
426 [&]( const std::unique_ptr<APPEARANCE_SETTING_3D>& aSetting )
427 {
428 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
429 int layer = aSetting->m_Id;
430
431 aSetting->m_Visible = visibleLayers.test( layer );
432
433 if( colors.count( layer ) )
434 {
435 COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowLayers, colors[ layer ], layer,
436 COLOR4D::WHITE, defaultColors[ layer ],
437 SWATCH_SMALL );
438 swatch->SetToolTip( _( "Left double click or middle click to change color" ) );
439
440 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
441 aSetting->m_Ctl_color = swatch;
442
443 swatch->Bind( COLOR_SWATCH_CHANGED,
444 [this]( wxCommandEvent& event )
445 {
446 auto swatch = static_cast<COLOR_SWATCH*>( event.GetEventObject() );
447 onColorSwatchChanged( swatch );
448
449 passOnFocus();
450 } );
451 }
452 else
453 {
454 sizer->AddSpacer( swatchWidth );
455 }
456
457 sizer->AddSpacer( 5 );
458
459 wxStaticText* label = new wxStaticText( m_windowLayers, layer, aSetting->GetLabel() );
460 label->Wrap( -1 );
461 label->SetToolTip( aSetting->GetTooltip() );
462
463 if( layer == LAYER_3D_BACKGROUND_TOP || layer == LAYER_3D_BACKGROUND_BOTTOM )
464 {
465 sizer->AddSpacer( swatchWidth );
466 }
467 else
468 {
469 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowLayers, layer,
470 KiBitmap( BITMAPS::visibility ),
471 KiBitmap( BITMAPS::visibility_off ),
472 aSetting->m_Visible );
473
474 btn_visible->Bind( TOGGLE_CHANGED,
475 [this]( wxCommandEvent& aEvent )
476 {
477 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
478 bool isVisible = aEvent.GetInt();
479 OnLayerVisibilityChanged( id, isVisible );
480
481 passOnFocus();
482 } );
483
484 wxString tip;
485 tip.Printf( _( "Show or hide %s" ), aSetting->GetLabel().Lower() );
486 btn_visible->SetToolTip( tip );
487
488 aSetting->m_Ctl_visibility = btn_visible;
489 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
490 }
491
492 sizer->AddSpacer( 5 );
493 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
494
495 m_layersOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
496 m_layersOuterSizer->AddSpacer( 2 );
497 };
498
499 for( const APPEARANCE_SETTING_3D& s_setting : s_layerSettings )
500 {
501 m_layerSettings.emplace_back( std::make_unique<APPEARANCE_SETTING_3D>( s_setting ) );
502 std::unique_ptr<APPEARANCE_SETTING_3D>& setting = m_layerSettings.back();
503
504 if( setting->m_Spacer )
505 m_layersOuterSizer->AddSpacer( m_pointSize );
506 else
507 appendLayer( setting );
508
509 m_layerSettingsMap[setting->m_Id] = setting.get();
510 }
511
512 m_sizerOuter->Layout();
513}
514
515
517{
518 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
519 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
520
521 for( std::unique_ptr<APPEARANCE_SETTING_3D>& setting : m_layerSettings )
522 {
523 if( setting->m_Spacer )
524 continue;
525
526 if( setting->m_Ctl_visibility )
527 setting->m_Ctl_visibility->SetValue( visibleLayers.test( setting->m_Id ) );
528
529 if( setting->m_Ctl_color )
530 setting->m_Ctl_color->SetSwatchColor( colors[ setting->m_Id ], false );
531 }
532}
533
534
536{
537 m_presetsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ),
539
540 m_cbLayerPresets->Clear();
541
542 // Build the layers preset list.
543
544 m_cbLayerPresets->Append( _( "Follow PCB Editor" ) );
545 m_cbLayerPresets->Append( _( "Follow PCB Plot Settings" ) );
546
547 for( const LAYER_PRESET_3D& preset : m_frame->GetAdapter().m_Cfg->m_LayerPresets )
548 m_cbLayerPresets->Append( preset.name );
549
550 m_cbLayerPresets->Append( wxT( "---" ) );
551 m_cbLayerPresets->Append( _( "Save preset..." ) );
552 m_cbLayerPresets->Append( _( "Delete preset..." ) );
553
555}
556
557
559{
560 m_frame->GetAdapter().m_Cfg->m_CurrentPreset = wxEmptyString;
561
562 std::vector<LAYER_PRESET_3D>& presets = m_frame->GetAdapter().m_Cfg->m_LayerPresets;
563 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
564 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
565
566 auto it = std::find_if( presets.begin(), presets.end(),
567 [&]( const LAYER_PRESET_3D& aPreset )
568 {
569 for( int layer = LAYER_3D_BOARD; layer < LAYER_3D_END; ++layer )
570 {
571 if( aPreset.layers.test( layer ) != visibleLayers.test( layer ) )
572 return false;
573 }
574
575 for( int layer : { LAYER_FP_REFERENCES, LAYER_FP_VALUES, LAYER_FP_TEXT } )
576 {
577 if( aPreset.layers.test( layer ) != visibleLayers.test( layer ) )
578 return false;
579 }
580
581 for( int layer = LAYER_3D_BOARD; layer < LAYER_3D_ADHESIVE; ++layer )
582 {
583 if( aPreset.colors.at( layer ) != colors.at( layer ) )
584 return false;
585 }
586
587 return true;
588 } );
589
590 if( it != presets.end() )
591 {
592 m_frame->GetAdapter().m_Cfg->m_CurrentPreset = it->name;
593 m_cbLayerPresets->SetStringSelection( it->name );
594 }
595 else
596 {
597 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
598 }
599}
600
601
603{
604 if( aName == FOLLOW_PCB )
605 m_cbLayerPresets->SetSelection( 0 );
606 else if( aName == FOLLOW_PLOT_SETTINGS )
607 m_cbLayerPresets->SetSelection( 1 );
608 else if( !m_cbLayerPresets->SetStringSelection( aName ) )
609 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
610}
611
612
614{
616 int count = m_cbLayerPresets->GetCount();
617 int index = m_cbLayerPresets->GetSelection();
618 wxString name;
619
620 auto resetSelection =
621 [&]()
622 {
624 };
625
626 if( index == 0 )
627 {
629 cfg->m_CurrentPreset = name;
631 m_frame->NewDisplay( true );
632 }
633 else if( index == 1 )
634 {
636 cfg->m_CurrentPreset = name;
638 m_frame->NewDisplay( true );
639 }
640 else if( index == count - 3 )
641 {
642 // Separator: reject the selection
643 resetSelection();
644 return;
645 }
646 else if( index == count - 2 )
647 {
648 wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ) );
649
650 if( dlg.ShowModal() != wxID_OK )
651 {
652 resetSelection();
653 return;
654 }
655
656 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
657 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
658
659 name = dlg.GetValue();
660
661 if( LAYER_PRESET_3D* preset = cfg->FindPreset( name ) )
662 {
663 if( !IsOK( this, _( "Overwrite existing preset?" ) ) )
664 {
665 resetSelection();
666 return;
667 }
668
669 preset->layers = visibleLayers;
670 preset->colors = colors;
671 m_cbLayerPresets->SetSelection( m_cbLayerPresets->FindString( name ) );
672 }
673 else
674 {
675 cfg->m_LayerPresets.emplace_back( name, visibleLayers, colors );
676 m_cbLayerPresets->SetSelection( m_cbLayerPresets->Insert( name, index - 1 ) );
677 }
678
679 cfg->m_CurrentPreset = name;
680 m_presetMRU.Insert( name, 0 );
681
682 return;
683 }
684 else if( index == count - 1 )
685 {
686 wxArrayString headers;
687 std::vector<wxArrayString> items;
688
689 headers.Add( _( "Presets" ) );
690
691 for( LAYER_PRESET_3D& preset : cfg->m_LayerPresets )
692 {
693 wxArrayString item;
694 item.Add( preset.name );
695 items.emplace_back( item );
696 }
697
698 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
699 dlg.SetListLabel( _( "Select preset:" ) );
700
701 if( dlg.ShowModal() == wxID_OK )
702 {
703 name = dlg.GetTextSelection();
704
705 if( m_cbLayerPresets->FindString( name ) != wxNOT_FOUND )
706 m_cbLayerPresets->Delete( m_cbLayerPresets->FindString( name ) );
707
709 [name]( const LAYER_PRESET_3D& preset )
710 {
711 return preset.name == name;
712 } );
713
714 if( cfg->m_CurrentPreset == name )
715 cfg->m_CurrentPreset = wxEmptyString;
716
717 m_presetMRU.Remove( name );
718 }
719
720 resetSelection();
721 return;
722 }
723 else if( LAYER_PRESET_3D* preset = cfg->FindPreset( m_cbLayerPresets->GetStringSelection() ) )
724 {
725 name = preset->name;
726 doApplyLayerPreset( *preset );
727 }
728
729 // Move to front of MRU list
730 if( m_presetMRU.Index( name ) != wxNOT_FOUND )
731 m_presetMRU.Remove( name );
732
733 m_presetMRU.Insert( name, 0 );
734
735 passOnFocus();
736}
737
738
740{
741 BOARD_ADAPTER& adapter = m_frame->GetAdapter();
742
743 adapter.m_Cfg->m_CurrentPreset = aPreset.name;
744 adapter.SetVisibleLayers( aPreset.layers );
745 adapter.SetLayerColors( aPreset.colors );
746
748 m_frame->NewDisplay( true );
749}
750
751
753{
754 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
756
757 m_cbViewports->Clear();
758
759 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
760 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
761
762 m_cbViewports->Append( wxT( "---" ) );
763 m_cbViewports->Append( _( "Save viewport..." ) );
764 m_cbViewports->Append( _( "Delete viewport..." ) );
765
766 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
767 m_lastSelectedViewport = nullptr;
768}
769
770
771void APPEARANCE_CONTROLS_3D::onViewportChanged( wxCommandEvent& aEvent )
772{
773 int count = m_cbViewports->GetCount();
774 int index = m_cbViewports->GetSelection();
775
776 if( index >= 0 && index < count - 3 )
777 {
778 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
779
780 wxCHECK( viewport, /* void */ );
781
782 doApplyViewport( *viewport );
783
784 if( !viewport->name.IsEmpty() )
785 {
786 m_viewportMRU.Remove( viewport->name );
787 m_viewportMRU.Insert( viewport->name, 0 );
788 }
789 }
790 else if( index == count - 2 )
791 {
792 // Save current state to new preset
793 wxString name;
794
795 wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name );
796
797 if( dlg.ShowModal() != wxID_OK )
798 {
800 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
801 else
802 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
803
804 return;
805 }
806
807 name = dlg.GetValue();
808 bool exists = m_viewports.count( name );
809
810 if( !exists )
811 {
813
814 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
815 }
816 else
817 {
819 index = m_cbViewports->FindString( name );
820 m_viewportMRU.Remove( name );
821 }
822
823 m_cbViewports->SetSelection( index );
824 m_viewportMRU.Insert( name, 0 );
825
826 return;
827 }
828 else if( index == count - 1 )
829 {
830 // Delete an existing viewport
831 wxArrayString headers;
832 std::vector<wxArrayString> items;
833
834 headers.Add( _( "Viewports" ) );
835
836 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
837 {
838 wxArrayString item;
839 item.Add( pair.first );
840 items.emplace_back( item );
841 }
842
843 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
844 dlg.SetListLabel( _( "Select viewport:" ) );
845
846 if( dlg.ShowModal() == wxID_OK )
847 {
848 wxString viewportName = dlg.GetTextSelection();
849 int idx = m_cbViewports->FindString( viewportName );
850
851 if( idx != wxNOT_FOUND )
852 {
853 m_viewports.erase( viewportName );
854 m_cbViewports->Delete( idx );
855 m_viewportMRU.Remove( viewportName );
856 }
857 }
858
860 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
861 else
862 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
863
864 return;
865 }
866
867 passOnFocus();
868}
869
870
871void APPEARANCE_CONTROLS_3D::onUpdateViewportsCb( wxUpdateUIEvent& aEvent )
872{
873 int count = m_cbViewports->GetCount();
874 int index = m_cbViewports->GetSelection();
875
876 if( index >= 0 && index < count - 3 )
877 {
878 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
879
880 wxCHECK( viewport, /* void */ );
881
882 if( m_frame->GetCurrentCamera().GetViewMatrix() != viewport->matrix )
883 m_cbViewports->SetSelection( -1 );
884 }
885}
886
887
889{
891
892 if( m_frame->GetAdapter().m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
894 else
896}
897
898
900{
901 m_focusOwner->SetFocus();
902}
903
904
const char * name
Definition: DXF_plotter.cpp:57
#define RR
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104
Container for an appearance setting (can control a layer class, object type, etc.)
Class APPEARANCE_CONTROLS_3D_BASE.
GRID_BITMAP_TOGGLE_RENDERER * m_toggleGridRenderer
void onLayerPresetChanged(wxCommandEvent &aEvent) override
void updateLayerPresetWidget(const wxString &aName)
std::vector< VIEWPORT3D > GetUserViewports() const
Update the current viewports from those saved in the project file.
void ApplyViewport(const wxString &aPresetName)
void onColorSwatchChanged(COLOR_SWATCH *aSwatch)
APPEARANCE_CONTROLS_3D(EDA_3D_VIEWER_FRAME *aParent, wxWindow *aFocusOwner)
std::vector< std::unique_ptr< APPEARANCE_SETTING_3D > > m_layerSettings
std::map< int, APPEARANCE_SETTING_3D * > m_layerSettingsMap
static const APPEARANCE_SETTING_3D s_layerSettings[]
Template for object appearance settings.
void doApplyLayerPreset(const LAYER_PRESET_3D &aPreset)
EDA_3D_VIEWER_FRAME * m_frame
void onUpdateViewportsCb(wxUpdateUIEvent &aEvent) override
void OnSetFocus(wxFocusEvent &aEvent) override
void OnLayerVisibilityChanged(int aLayer, bool isVisible)
void OnSize(wxSizeEvent &aEvent) override
void doApplyViewport(const VIEWPORT3D &aViewport)
std::map< wxString, VIEWPORT3D > m_viewports
void ApplyLayerPreset(const wxString &aPresetName)
void onViewportChanged(wxCommandEvent &aEvent) override
void SetUserViewports(std::vector< VIEWPORT3D > &aPresetList)
A checkbox control except with custom bitmaps for the checked and unchecked states.
Definition: bitmap_toggle.h:45
Helper class to handle information needed to display 3D board.
Definition: board_adapter.h:71
void SetVisibleLayers(const std::bitset< LAYER_3D_END > &aLayers)
std::map< int, COLOR4D > GetLayerColors() const
std::bitset< LAYER_3D_END > GetVisibleLayers() const
void SetLayerColors(const std::map< int, COLOR4D > &aColors)
EDA_3D_VIEWER_SETTINGS * m_Cfg
std::map< int, COLOR4D > GetDefaultColors() const
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
A simple color swatch of the kind used to set layer colors.
Definition: color_swatch.h:57
KIGFX::COLOR4D GetSwatchColor() const
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
double GetContentScaleFactor() const override
Get the content scale factor, which may be different from the scale factor on some platforms.
double GetScaleFactor() const override
Get the DPI scale from all known sources in order:
static TOOL_ACTION showNotInPosFile
static TOOL_ACTION showTHT
static TOOL_ACTION showDNP
static TOOL_ACTION showSMD
static TOOL_ACTION showVirtual
static TOOL_ACTION showBBoxes
static TOOL_ACTION showAxis
RENDER_3D_BASE * GetCurrentRender() const
void RenderRaytracingRequest()
Request to render the current view in Raytracing mode.
void Request_refresh(bool aRedrawImmediately=true)
Schedule a refresh update of the canvas.
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
BOARD_ADAPTER & GetAdapter() override
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
CAMERA & GetCurrentCamera() override
EDA_3D_CANVAS * GetCanvas()
LAYER_PRESET_3D * FindPreset(const wxString &aName)
std::vector< LAYER_PRESET_3D > m_LayerPresets
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)
A toggle button renderer for a wxGrid, similar to BITMAP_TOGGLE.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
Object to render the board using openGL.
void Load3dModelsIfNeeded()
Load footprint models if they are not already loaded, i.e.
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition: wx_panel.h:39
@ SWATCH_SMALL
Definition: color_swatch.h:40
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:360
This file is part of the common library.
#define _HKI(x)
#define _(s)
Declaration of the eda_3d_viewer class.
#define FOLLOW_PLOT_SETTINGS
#define FOLLOW_PCB
#define VIEWPORT_SWITCH_KEY
#define PRESET_SWITCH_KEY
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
@ LAYER_3D_SOLDERMASK_TOP
Definition: layer_ids.h:451
@ LAYER_3D_BOUNDING_BOXES
Definition: layer_ids.h:464
@ LAYER_3D_ADHESIVE
Definition: layer_ids.h:453
@ LAYER_3D_SMD_MODELS
Definition: layer_ids.h:459
@ LAYER_3D_BACKGROUND_TOP
Definition: layer_ids.h:444
@ LAYER_3D_USER_COMMENTS
Definition: layer_ids.h:454
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition: layer_ids.h:450
@ LAYER_3D_BOARD
Definition: layer_ids.h:445
@ LAYER_3D_USER_ECO1
Definition: layer_ids.h:456
@ LAYER_3D_USER_ECO2
Definition: layer_ids.h:457
@ LAYER_3D_TH_MODELS
Definition: layer_ids.h:458
@ LAYER_3D_AXES
Definition: layer_ids.h:463
@ LAYER_3D_SILKSCREEN_TOP
Definition: layer_ids.h:449
@ LAYER_3D_VIRTUAL_MODELS
Definition: layer_ids.h:460
@ LAYER_3D_MODELS_MARKED_DNP
Definition: layer_ids.h:462
@ LAYER_3D_COPPER_TOP
Definition: layer_ids.h:446
@ LAYER_3D_SOLDERPASTE
Definition: layer_ids.h:452
@ LAYER_3D_OFF_BOARD_SILK
Definition: layer_ids.h:465
@ LAYER_3D_MODELS_NOT_IN_POS
Definition: layer_ids.h:461
@ LAYER_3D_USER_DRAWINGS
Definition: layer_ids.h:455
@ LAYER_3D_COPPER_BOTTOM
Definition: layer_ids.h:447
@ LAYER_3D_BACKGROUND_BOTTOM
Definition: layer_ids.h:443
@ LAYER_3D_SILKSCREEN_BOTTOM
Definition: layer_ids.h:448
@ LAYER_FP_REFERENCES
show footprints references (when texts are visible)
Definition: layer_ids.h:212
@ LAYER_FP_TEXT
Definition: layer_ids.h:199
@ LAYER_FP_VALUES
show footprints values (when texts are visible)
Definition: layer_ids.h:211
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:151
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
Definition: kicad_algo.h:174
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
see class PGM_BASE
wxString name
A name for this layer set.
std::bitset< LAYER_3D_END > layers
std::map< int, KIGFX::COLOR4D > colors