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 The 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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <../3d_rendering/opengl/render_3d_opengl.h> // Must be included before any GL header
22
24
25#include <bitmaps.h>
27#include <confirm.h>
28#include <pgm_base.h>
29#include <dpi_scaling_common.h>
30#include <eda_list_dialog.h>
31#include <pcb_display_options.h>
32#include <eda_3d_viewer_frame.h>
33#include <pcbnew_settings.h>
34#include <project.h>
35#include <board.h>
36#include <layer_range.h>
37#include <tool/tool_manager.h>
38#include <tools/pcb_actions.h>
42#include <widgets/wx_infobar.h>
45#include <wx/bmpbuttn.h>
46#include <wx/sizer.h>
47#include <wx/textdlg.h>
48#include <wx/checkbox.h>
49#include <wx/menu.h>
50
51#include <algorithm>
52
53static constexpr int ID_SHOW_ALL_COPPER_LAYERS = wxID_HIGHEST + 1;
57
59#define RR APPEARANCE_CONTROLS_3D::APPEARANCE_SETTING_3D
60
63
64 // text id tooltip
65 RR( _HKI( "Board Body" ), LAYER_3D_BOARD, _HKI( "Show board body" ) ),
66 RR( _HKI( "Plated Barrels" ),LAYER_3D_PLATED_BARRELS, _HKI( "Show barrels of plated through-holes and vias" ) ),
67 RR( wxS( "F.Cu" ), LAYER_3D_COPPER_TOP, _HKI( "Show front copper / surface finish color" ) ),
68 RR( wxS( "B.Cu" ), LAYER_3D_COPPER_BOTTOM, _HKI( "Show back copper / surface finish color" ) ),
69 RR( _HKI( "Adhesive" ), LAYER_3D_ADHESIVE, _HKI( "Show adhesive" ) ),
70 RR( _HKI( "Solder Paste" ), LAYER_3D_SOLDERPASTE, _HKI( "Show solder paste" ) ),
71 RR( wxS( "F.Silkscreen" ), LAYER_3D_SILKSCREEN_TOP, _HKI( "Show front silkscreen" ) ),
72 RR( wxS( "B.Silkscreen" ), LAYER_3D_SILKSCREEN_BOTTOM, _HKI( "Show back silkscreen" ) ),
73 RR( wxS( "F.Mask" ), LAYER_3D_SOLDERMASK_TOP, _HKI( "Show front solder mask" ) ),
74 RR( wxS( "B.Mask" ), LAYER_3D_SOLDERMASK_BOTTOM, _HKI( "Show back solder mask" ) ),
75 RR( wxS( "User.Drawings" ), LAYER_3D_USER_DRAWINGS, _HKI( "Show user drawings layer" ) ),
76 RR( wxS( "User.Comments" ), LAYER_3D_USER_COMMENTS, _HKI( "Show user comments layer" ) ),
77 RR( wxS( "User.Eco1" ), LAYER_3D_USER_ECO1, _HKI( "Show user ECO1 layer" ) ),
78 RR( wxS( "User.Eco2" ), LAYER_3D_USER_ECO2, _HKI( "Show user ECO2 layer" ) ),
79 RR( wxS( "F.Fab" ), LAYER_3D_F_FAB, _HKI( "Show front fabrication layer" ) ),
80 RR( wxS( "B.Fab" ), LAYER_3D_B_FAB, _HKI( "Show back fabrication layer" ) ),
81 RR( wxS( "F.Courtyard" ), LAYER_3D_F_COURTYARD, _HKI( "Show front courtyard layer" ) ),
82 RR( wxS( "B.Courtyard" ), LAYER_3D_B_COURTYARD, _HKI( "Show back courtyard layer" ) ),
83 RR( wxS( "User.1" ), LAYER_3D_USER_1, _HKI( "Show user defined layer 1" ) ),
84 RR( wxS( "User.2" ), LAYER_3D_USER_2, _HKI( "Show user defined layer 2" ) ),
85 RR( wxS( "User.3" ), LAYER_3D_USER_3, _HKI( "Show user defined layer 3" ) ),
86 RR( wxS( "User.4" ), LAYER_3D_USER_4, _HKI( "Show user defined layer 4" ) ),
87 RR( wxS( "User.5" ), LAYER_3D_USER_5, _HKI( "Show user defined layer 5" ) ),
88 RR( wxS( "User.6" ), LAYER_3D_USER_6, _HKI( "Show user defined layer 6" ) ),
89 RR( wxS( "User.7" ), LAYER_3D_USER_7, _HKI( "Show user defined layer 7" ) ),
90 RR( wxS( "User.8" ), LAYER_3D_USER_8, _HKI( "Show user defined layer 8" ) ),
91 RR( wxS( "User.9" ), LAYER_3D_USER_9, _HKI( "Show user defined layer 9" ) ),
92 RR( wxS( "User.10" ), LAYER_3D_USER_10, _HKI( "Show user defined layer 10" ) ),
93 RR( wxS( "User.11" ), LAYER_3D_USER_11, _HKI( "Show user defined layer 11" ) ),
94 RR( wxS( "User.12" ), LAYER_3D_USER_12, _HKI( "Show user defined layer 12" ) ),
95 RR( wxS( "User.13" ), LAYER_3D_USER_13, _HKI( "Show user defined layer 13" ) ),
96 RR( wxS( "User.14" ), LAYER_3D_USER_14, _HKI( "Show user defined layer 14" ) ),
97 RR( wxS( "User.15" ), LAYER_3D_USER_15, _HKI( "Show user defined layer 15" ) ),
98 RR( wxS( "User.16" ), LAYER_3D_USER_16, _HKI( "Show user defined layer 16" ) ),
99 RR( wxS( "User.17" ), LAYER_3D_USER_17, _HKI( "Show user defined layer 17" ) ),
100 RR( wxS( "User.18" ), LAYER_3D_USER_18, _HKI( "Show user defined layer 18" ) ),
101 RR( wxS( "User.19" ), LAYER_3D_USER_19, _HKI( "Show user defined layer 19" ) ),
102 RR( wxS( "User.20" ), LAYER_3D_USER_20, _HKI( "Show user defined layer 20" ) ),
103 RR( wxS( "User.21" ), LAYER_3D_USER_21, _HKI( "Show user defined layer 21" ) ),
104 RR( wxS( "User.22" ), LAYER_3D_USER_22, _HKI( "Show user defined layer 22" ) ),
105 RR( wxS( "User.23" ), LAYER_3D_USER_23, _HKI( "Show user defined layer 23" ) ),
106 RR( wxS( "User.24" ), LAYER_3D_USER_24, _HKI( "Show user defined layer 24" ) ),
107 RR( wxS( "User.25" ), LAYER_3D_USER_25, _HKI( "Show user defined layer 25" ) ),
108 RR( wxS( "User.26" ), LAYER_3D_USER_26, _HKI( "Show user defined layer 26" ) ),
109 RR( wxS( "User.27" ), LAYER_3D_USER_27, _HKI( "Show user defined layer 27" ) ),
110 RR( wxS( "User.28" ), LAYER_3D_USER_28, _HKI( "Show user defined layer 28" ) ),
111 RR( wxS( "User.29" ), LAYER_3D_USER_29, _HKI( "Show user defined layer 29" ) ),
112 RR( wxS( "User.30" ), LAYER_3D_USER_30, _HKI( "Show user defined layer 30" ) ),
113 RR( wxS( "User.31" ), LAYER_3D_USER_31, _HKI( "Show user defined layer 31" ) ),
114 RR( wxS( "User.32" ), LAYER_3D_USER_32, _HKI( "Show user defined layer 32" ) ),
115 RR( wxS( "User.33" ), LAYER_3D_USER_33, _HKI( "Show user defined layer 33" ) ),
116 RR( wxS( "User.34" ), LAYER_3D_USER_34, _HKI( "Show user defined layer 34" ) ),
117 RR( wxS( "User.35" ), LAYER_3D_USER_35, _HKI( "Show user defined layer 35" ) ),
118 RR( wxS( "User.36" ), LAYER_3D_USER_36, _HKI( "Show user defined layer 36" ) ),
119 RR( wxS( "User.37" ), LAYER_3D_USER_37, _HKI( "Show user defined layer 37" ) ),
120 RR( wxS( "User.38" ), LAYER_3D_USER_38, _HKI( "Show user defined layer 38" ) ),
121 RR( wxS( "User.39" ), LAYER_3D_USER_39, _HKI( "Show user defined layer 39" ) ),
122 RR( wxS( "User.40" ), LAYER_3D_USER_40, _HKI( "Show user defined layer 40" ) ),
123 RR( wxS( "User.41" ), LAYER_3D_USER_41, _HKI( "Show user defined layer 41" ) ),
124 RR( wxS( "User.42" ), LAYER_3D_USER_42, _HKI( "Show user defined layer 42" ) ),
125 RR( wxS( "User.43" ), LAYER_3D_USER_43, _HKI( "Show user defined layer 43" ) ),
126 RR( wxS( "User.44" ), LAYER_3D_USER_44, _HKI( "Show user defined layer 44" ) ),
127 RR( wxS( "User.45" ), LAYER_3D_USER_45, _HKI( "Show user defined layer 45" ) ),
128 RR(),
129 RR( _HKI( "Through-hole Models" ), LAYER_3D_TH_MODELS, EDA_3D_ACTIONS::showTHT ),
133 RR( _HKI( "Models marked DNP" ), LAYER_3D_MODELS_MARKED_DNP, EDA_3D_ACTIONS::showDNP ),
134 RR( _HKI( "Model Bounding Boxes" ), LAYER_3D_BOUNDING_BOXES, EDA_3D_ACTIONS::showBBoxes ),
135 RR(),
136 RR( _HKI( "Values" ), LAYER_FP_VALUES, _HKI( "Show footprint values" ) ),
137 RR( _HKI( "References" ), LAYER_FP_REFERENCES, _HKI( "Show footprint references" ) ),
138 RR( _HKI( "Footprint Text" ), LAYER_FP_TEXT, _HKI( "Show all footprint text" ) ),
139 RR( _HKI( "Off-board Silkscreen" ), LAYER_3D_OFF_BOARD_SILK, _HKI( "Do not clip silk layers to board outline" ) ),
140 RR(),
142 RR( _HKI( "Background Start" ), LAYER_3D_BACKGROUND_TOP, _HKI( "Background gradient start color" ) ),
143 RR( _HKI( "Background End" ), LAYER_3D_BACKGROUND_BOTTOM, _HKI( "Background gradient end color" ) ),
144};
145
146
147// The 3D viewer uses a single color for all copper layers.
148static bool isCopperLayer3D( int aLayer )
149{
150 return aLayer == LAYER_3D_COPPER_TOP
151 || aLayer == LAYER_3D_COPPER_BOTTOM
152 || aLayer == LAYER_3D_PLATED_BARRELS
154}
155
156
157// Layers that can have colors coming from the board stackup, and cannot be modified if
158// use colors from stackup is activated.
159static bool isStackupColorLayer3D( int aLayer )
160{
161 return aLayer == LAYER_3D_BOARD
162 || aLayer == LAYER_3D_SOLDERPASTE
163 || aLayer == LAYER_3D_SILKSCREEN_TOP
164 || aLayer == LAYER_3D_SILKSCREEN_BOTTOM
165 || aLayer == LAYER_3D_SOLDERMASK_TOP
166 || aLayer == LAYER_3D_SOLDERMASK_BOTTOM
167 || isCopperLayer3D( aLayer );
168}
169
170
173 m_frame( aParent ),
174 m_focusOwner( aFocusOwner ),
175 m_lastSelectedViewport( nullptr )
176{
177 DPI_SCALING_COMMON dpi( nullptr, m_frame );
178
179 int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
180 m_pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
181
182 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
183 SetBorders( true, false, false, false );
184
185 m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
187 m_windowLayers->SetScrollRate( 0, 5 );
188 m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS_3D::OnSetFocus, this );
189 m_panelLayers->Bind( wxEVT_CONTEXT_MENU, &APPEARANCE_CONTROLS_3D::OnLayerContextMenu, this );
190
191 m_envOuterSizer = new wxBoxSizer( wxVERTICAL );
192
193 wxFont infoFont = KIUI::GetInfoFont( this );
194 m_panelLayers->SetFont( infoFont );
195 m_windowLayers->SetFont( infoFont );
196 m_presetsLabel->SetFont( infoFont );
197 m_viewportsLabel->SetFont( infoFont );
198
199 // Create display options
200 m_cbUseBoardStackupColors = new wxCheckBox( m_panelLayers, wxID_ANY,
201 _( "Use board stackup colors" ) );
202 m_cbUseBoardStackupColors->SetFont( infoFont );
203
204 m_cbUseBoardStackupColors->Bind( wxEVT_CHECKBOX,
205 [this]( wxCommandEvent& aEvent )
206 {
207 EDA_3D_VIEWER_SETTINGS* cfg = m_frame->GetAdapter().m_Cfg;
208 cfg->m_UseStackupColors = aEvent.IsChecked();
209
211 m_frame->NewDisplay( true );
212 } );
213
214 m_cbUseBoardEditorCopperColors = new wxCheckBox( m_panelLayers, wxID_ANY,
215 _( "Use PCB editor copper colors" ) );
216 m_cbUseBoardEditorCopperColors->SetFont( infoFont );
217 m_cbUseBoardEditorCopperColors->SetToolTip( _( "Use the board editor layer colors for copper "
218 "layers (realtime renderer only)" ) );
219
220 m_cbUseBoardEditorCopperColors->Bind( wxEVT_CHECKBOX,
221 [this]( wxCommandEvent& aEvent )
222 {
223 EDA_3D_VIEWER_SETTINGS* cfg = m_frame->GetAdapter().m_Cfg;
224 cfg->m_Render.use_board_editor_copper_colors = aEvent.IsChecked();
225
227 m_frame->NewDisplay( true );
228 } );
229
230 m_panelLayersSizer->Add( m_cbUseBoardStackupColors, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5 );
232 wxEXPAND | wxALL, 5 );
233
234 m_cbLayerPresets->SetToolTip( wxString::Format( _( "Save and restore color and visibility combinations.\n"
235 "Use %s+Tab to activate selector.\n"
236 "Successive Tabs while holding %s down will cycle through "
237 "presets in the popup." ),
240
241 m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore camera position and zoom.\n"
242 "Use %s+Tab to activate selector.\n"
243 "Successive Tabs while holding %s down will cycle through "
244 "viewports in the popup." ),
247
248 if( screenHeight <= 900 && m_pointSize >= FromDIP( KIUI::c_IndicatorSizeDIP ) )
249 m_pointSize = m_pointSize * 8 / 10;
250
252
255
256 m_frame->Bind( EDA_LANG_CHANGED, &APPEARANCE_CONTROLS_3D::OnLanguageChanged, this );
257}
258
259
264
265
267{
268 DPI_SCALING_COMMON dpi( nullptr, m_frame );
269 wxSize size( 220 * dpi.GetScaleFactor(), 480 * dpi.GetScaleFactor() );
270 return size;
271}
272
273
274void APPEARANCE_CONTROLS_3D::OnLayerContextMenu( wxContextMenuEvent& aEvent )
275{
276 wxMenu menu;
277
278 menu.Append( ID_SHOW_ALL_COPPER_LAYERS, _( "Show All Copper Layers" ) );
279 menu.Append( ID_HIDE_ALL_COPPER_LAYERS, _( "Hide All Copper Layers" ) );
280 menu.AppendSeparator();
281 menu.Append( ID_SHOW_ALL_INNER_LAYERS, _( "Show All Inner Layers" ) );
282 menu.Append( ID_HIDE_ALL_INNER_LAYERS, _( "Hide All Inner Layers" ) );
283
284 BOARD* board = m_frame->GetBoard();
285 bool hasInnerLayers = board && board->GetCopperLayerCount() > 2;
286
287 menu.Enable( ID_SHOW_ALL_INNER_LAYERS, hasInnerLayers );
288 menu.Enable( ID_HIDE_ALL_INNER_LAYERS, hasInnerLayers );
289
290 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
291
292 auto setInnerCopperLayers =
293 [&]( bool aVisible )
294 {
295 if( !board )
296 return;
297
298 for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, board->GetCopperLayerCount() ) )
299 {
300 if( IsInnerCopperLayer( layer ) )
301 visibleLayers.set( MapPCBLayerTo3DLayer( layer ), aVisible );
302 }
303 };
304
305 switch( GetPopupMenuSelectionFromUser( menu ) )
306 {
308 visibleLayers.set( LAYER_3D_COPPER_TOP );
309 visibleLayers.set( LAYER_3D_COPPER_BOTTOM );
310 setInnerCopperLayers( true );
311 break;
312
314 visibleLayers.reset( LAYER_3D_COPPER_TOP );
315 visibleLayers.reset( LAYER_3D_COPPER_BOTTOM );
316 setInnerCopperLayers( false );
317 break;
318
320 setInnerCopperLayers( true );
321 break;
322
324 setInnerCopperLayers( false );
325 break;
326
327 default:
328 return;
329 }
330
331 m_frame->GetAdapter().SetVisibleLayers( visibleLayers );
334 m_frame->NewDisplay( true );
335}
336
337
338void APPEARANCE_CONTROLS_3D::OnSetFocus( wxFocusEvent& aEvent )
339{
340#ifdef __WXMSW__
341 // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
342 // focus and give it back to the parent in the button event handler.
343 if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
344 {
345 wxCommandEvent evt( wxEVT_BUTTON );
346 wxPostEvent( btn, evt );
347 }
348#endif
349
350 passOnFocus();
351 aEvent.Skip();
352}
353
354
355void APPEARANCE_CONTROLS_3D::OnSize( wxSizeEvent& aEvent )
356{
357 aEvent.Skip();
358}
359
360
362{
363 Freeze();
364
366 m_cbUseBoardStackupColors->SetLabel( _( "Use board stackup colors" ) );
369
370 Thaw();
371 Refresh();
372}
373
374
375void APPEARANCE_CONTROLS_3D::OnLanguageChanged( wxCommandEvent& aEvent )
376{
378
379 aEvent.Skip();
380}
381
382
384{
385 // This is essentially a list of hacks because DarkMode isn't yet implemented inside
386 // wxWidgets.
387 //
388 // The individual wxPanels, COLOR_SWATCHes and GRID_CELL_COLOR_RENDERERs should really be
389 // overriding some virtual method or responding to some wxWidgets event so that the parent
390 // doesn't have to know what it contains. But, that's not where we are, so... :shrug:
391
392 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
393
394 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
395
396 for( wxSizerItem* child : m_layersOuterSizer->GetChildren() )
397 {
398 if( child && child->GetWindow() )
399 child->GetWindow()->SetBackgroundColour( m_layerPanelColour );
400 }
401}
402
403
405{
407
409
410 const wxString& currentPreset = m_frame->GetAdapter().m_Cfg->m_CurrentPreset;
411
412 if( currentPreset == FOLLOW_PCB || currentPreset == FOLLOW_PLOT_SETTINGS )
413 updateLayerPresetWidget( currentPreset );
414 else
416}
417
418
419void APPEARANCE_CONTROLS_3D::ApplyLayerPreset( const wxString& aPresetName )
420{
421 doApplyLayerPreset( aPresetName );
422
423 // Move to front of MRU list
424 if( m_presetMRU.Index( aPresetName ) != wxNOT_FOUND )
425 m_presetMRU.Remove( aPresetName );
426
427 m_presetMRU.Insert( aPresetName, 0 );
428
429 updateLayerPresetWidget( aPresetName );
430}
431
432
433std::vector<VIEWPORT3D> APPEARANCE_CONTROLS_3D::GetUserViewports() const
434{
435 std::vector<VIEWPORT3D> ret;
436
437 for( const auto& [name, viewport] : m_viewports )
438 ret.emplace_back( viewport );
439
440 return ret;
441}
442
443
444void APPEARANCE_CONTROLS_3D::SetUserViewports( std::vector<VIEWPORT3D>& aViewportList )
445{
446 m_viewports.clear();
447
448 for( const VIEWPORT3D& viewport : aViewportList )
449 {
450 if( m_viewports.count( viewport.name ) )
451 continue;
452
453 m_viewports[viewport.name] = viewport;
454
455 m_viewportMRU.Add( viewport.name );
456 }
457
459
460 // Now is as good a time as any to initialize the layer presets as well.
462
463 m_presetMRU.Add( FOLLOW_PCB );
465
466 for( const LAYER_PRESET_3D& preset : m_frame->GetAdapter().m_Cfg->m_LayerPresets )
467 m_presetMRU.Add( preset.name );
468}
469
470
471void APPEARANCE_CONTROLS_3D::ApplyViewport( const wxString& aViewportName )
472{
473 int idx = m_cbViewports->FindString( aViewportName );
474
475 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
476 {
477 m_cbViewports->SetSelection( idx );
478 m_lastSelectedViewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( idx ) );
479 }
480 else
481 {
482 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
483 m_lastSelectedViewport = nullptr;
484 }
485
488}
489
490
491void APPEARANCE_CONTROLS_3D::OnLayerVisibilityChanged( int aLayer, bool isVisible )
492{
493 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
494 const std::map<int, COLOR4D>& colors = m_frame->GetAdapter().GetLayerColors();
495 bool killFollow = false;
496 bool doFastRefresh = false; // true to just refresh the display
497
498 // Special-case controls
499 switch( aLayer )
500 {
501 case LAYER_FP_TEXT:
502 // Because Footprint Text is a meta-control that also can disable values/references,
503 // drag them along here so that the user is less likely to be confused.
504 if( !isVisible )
505 {
506 visibleLayers.set( LAYER_FP_REFERENCES, false );
507 visibleLayers.set( LAYER_FP_VALUES, false );
508 }
509
510 visibleLayers.set( LAYER_FP_TEXT, isVisible );
511 killFollow = true;
512 break;
513
515 case LAYER_FP_VALUES:
516 // In case that user changes Footprint Value/References when the Footprint Text
517 // meta-control is disabled, we should put it back on.
518 if( isVisible )
519 visibleLayers.set( LAYER_FP_TEXT, true );
520
521 visibleLayers.set( aLayer, isVisible );
522 killFollow = true;
523 break;
524
525 case LAYER_3D_BOARD:
539 case LAYER_3D_F_FAB:
540 case LAYER_3D_B_FAB:
543 visibleLayers.set( aLayer, isVisible );
544 killFollow = true;
545 break;
546
552 doFastRefresh = true;
553 visibleLayers.set( aLayer, isVisible );
554 break;
555
556 default:
557 visibleLayers.set( aLayer, isVisible );
558
559 if( ( aLayer >= LAYER_3D_USER_1 && aLayer <= LAYER_3D_USER_45 )
560 || ( aLayer >= LAYER_3D_COPPER_INNER_1 && aLayer <= LAYER_3D_COPPER_INNER_30 ) )
561 {
562 killFollow = true;
563 }
564
565 break;
566 }
567
568 m_frame->GetAdapter().SetVisibleLayers( visibleLayers );
569 m_frame->GetAdapter().SetLayerColors( colors );
570
571 const wxString& currentPreset = m_frame->GetAdapter().m_Cfg->m_CurrentPreset;
572
573 if( ( currentPreset != FOLLOW_PCB && currentPreset != FOLLOW_PLOT_SETTINGS ) || killFollow )
575
577
578 if( doFastRefresh && m_frame->GetAdapter().m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
579 {
580 RENDER_3D_OPENGL* renderer = static_cast<RENDER_3D_OPENGL*>( m_frame->GetCanvas()->GetCurrentRender() );
581 renderer->Load3dModelsIfNeeded();
582 renderer->RebuildHitTestAsync();
583 m_frame->GetCanvas()->Request_refresh();
584 }
585 else
586 {
587 m_frame->NewDisplay( true );
588 }
589}
590
591
593{
594 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
595 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
596
597 m_frame->GetAdapter().SetVisibleLayers( visibleLayers );
598
599 int layer = aSwatch->GetId();
600 COLOR4D newColor = aSwatch->GetSwatchColor();
601
602 // The internals of the 3D viewer only supports a single color for copper, which must
603 // be applied to all copper layers.
604 if( isCopperLayer3D( layer ) )
605 {
606 for( const auto& [index, setting] : m_layerSettingsMap )
607 {
608 if( !isCopperLayer3D( index ) )
609 continue;
610
611 if( colors.count( index ) )
612 colors[index] = newColor;
613
614 if( setting->m_Ctl_color )
615 {
616 // Don't send an event, because that will cause an event loop
617 setting->m_Ctl_color->SetSwatchColor( newColor, false );
618 }
619 }
620 }
621 else
622 {
623 colors[layer] = newColor;
624 }
625
626 m_frame->GetAdapter().SetLayerColors( colors );
627
628 const wxString& currentPreset = m_frame->GetAdapter().m_Cfg->m_CurrentPreset;
629
630 if( currentPreset == FOLLOW_PCB || currentPreset == FOLLOW_PLOT_SETTINGS )
631 updateLayerPresetWidget( currentPreset );
632 else
634
635 m_frame->NewDisplay( true );
636}
637
638
640{
641 int swatchWidth = m_windowLayers->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
642
643 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
644 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
645 std::map<int, COLOR4D> defaultColors = m_frame->GetAdapter().GetDefaultColors();
646 LSET enabled = m_frame->GetBoard()->GetEnabledLayers();
647
648 m_layerSettings.clear();
649 m_layerSettingsMap.clear();
650 m_layersOuterSizer->Clear( true );
651 m_layersOuterSizer->AddSpacer( 5 );
652
653 m_envOuterSizer->Clear( true );
654
655 const auto appendLayer =
656 [&]( const std::unique_ptr<APPEARANCE_SETTING_3D>& aSetting, int aColorLayer )
657 {
658 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
659 int layer = aSetting->m_Id;
660
661 aSetting->m_Visible = visibleLayers.test( layer );
662
663 if( colors.count( aColorLayer ) )
664 {
665 COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowLayers, colors[ aColorLayer ], layer,
666 COLOR4D::WHITE, defaultColors[ aColorLayer ],
667 SWATCH_SMALL );
668 swatch->SetToolTip( _( "Left double click or middle click to change color" ) );
669
670 swatch->SetReadOnlyCallback(
671 [this]()
672 {
673 WX_INFOBAR* infobar = m_frame->GetInfoBar();
674
675 infobar->RemoveAllButtons();
676 infobar->AddCloseButton();
677
678 infobar->ShowMessageFor( _( "Uncheck 'Use board stackup colors' to "
679 "allow color editing." ),
680 10000, wxICON_INFORMATION );
681 } );
682
683 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
684 aSetting->m_Ctl_color = swatch;
685
686 swatch->Bind( COLOR_SWATCH_CHANGED,
687 [this]( wxCommandEvent& event )
688 {
689 auto swatch = static_cast<COLOR_SWATCH*>( event.GetEventObject() );
690 onColorSwatchChanged( swatch );
691
692 passOnFocus();
693 } );
694 }
695 else
696 {
697 sizer->AddSpacer( swatchWidth );
698 }
699
700 sizer->AddSpacer( 5 );
701
702 wxString layerName = aSetting->GetLabel();
703 PCB_LAYER_ID boardLayer = Map3DLayerToPCBLayer( layer );
704
705 if( boardLayer != UNDEFINED_LAYER )
706 layerName = m_frame->GetBoard()->GetLayerName( boardLayer );
707
708 wxStaticText* label = new wxStaticText( m_windowLayers, layer, layerName );
709 label->Wrap( -1 );
710 label->SetToolTip( aSetting->GetTooltip() );
711
712 if( layer == LAYER_3D_BACKGROUND_TOP || layer == LAYER_3D_BACKGROUND_BOTTOM )
713 {
714 sizer->AddSpacer( swatchWidth );
715 }
716 else
717 {
718 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowLayers, layer,
721 aSetting->m_Visible );
722
723 btn_visible->Bind( TOGGLE_CHANGED,
724 [this]( wxCommandEvent& aEvent )
725 {
726 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
727 bool isVisible = aEvent.GetInt();
728 OnLayerVisibilityChanged( id, isVisible );
729
730 passOnFocus();
731 } );
732
733 wxString tip;
734 tip.Printf( _( "Show or hide %s" ), aSetting->GetLabel().Lower() );
735 btn_visible->SetToolTip( tip );
736
737 aSetting->m_Ctl_visibility = btn_visible;
738 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
739 }
740
741 sizer->AddSpacer( 5 );
742 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
743
744 m_layersOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
745 m_layersOuterSizer->AddSpacer( 2 );
746 };
747
748 const auto appendInnerLayers =
749 [&]()
750 {
751 BOARD& board = *m_frame->GetBoard();
752
753 for( PCB_LAYER_ID boardLayer : LAYER_RANGE( F_Cu, B_Cu, board.GetCopperLayerCount() ) )
754 {
755 if( !IsInnerCopperLayer( boardLayer ) || !enabled.test( boardLayer ) )
756 continue;
757
758 int layerId = MapPCBLayerTo3DLayer( boardLayer );
759 wxString label = board.GetLayerName( boardLayer );
760 wxString tooltip = wxString::Format( _( "Show %s" ), label );
761
762 m_layerSettings.emplace_back(
763 std::make_unique<APPEARANCE_SETTING_3D>( label, layerId, tooltip ) );
764 appendLayer( m_layerSettings.back(), LAYER_3D_COPPER_TOP );
765 m_layerSettingsMap[layerId] = m_layerSettings.back().get();
766 }
767 };
768
769 for( const APPEARANCE_SETTING_3D& s_setting : s_layerSettings )
770 {
771 m_layerSettings.emplace_back( std::make_unique<APPEARANCE_SETTING_3D>( s_setting ) );
772 std::unique_ptr<APPEARANCE_SETTING_3D>& setting = m_layerSettings.back();
773
774 if( setting->m_Spacer )
775 {
776 m_layersOuterSizer->AddSpacer( m_pointSize );
777 }
778 else if( setting->m_Id >= LAYER_3D_USER_1 && setting->m_Id <= LAYER_3D_USER_45 )
779 {
780 if( enabled.test( Map3DLayerToPCBLayer( setting->m_Id ) ) )
781 appendLayer( setting, setting->m_Id );
782 }
783 else
784 {
785 appendLayer( setting, setting->m_Id );
786 }
787
788 m_layerSettingsMap[setting->m_Id] = setting.get();
789
790 // Keep the inner copper rows next to the outer copper rows, in stack order.
791 if( setting->m_Id == LAYER_3D_COPPER_TOP )
792 appendInnerLayers();
793 }
794
795 m_sizerOuter->Layout();
796}
797
798
800{
801 EDA_3D_VIEWER_SETTINGS* cfg = m_frame->GetAdapter().m_Cfg;
802 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
803 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
804
805 for( std::unique_ptr<APPEARANCE_SETTING_3D>& setting : m_layerSettings )
806 {
807 if( setting->m_Spacer )
808 continue;
809
810 if( setting->m_Ctl_visibility )
811 setting->m_Ctl_visibility->SetValue( visibleLayers.test( setting->m_Id ) );
812
813 if( setting->m_Ctl_color )
814 {
815 bool isCopper = isCopperLayer3D( setting->m_Id );
816 int colorLayer = isCopper ? LAYER_3D_COPPER_TOP : setting->m_Id;
817
818 setting->m_Ctl_color->SetSwatchColor( colors[colorLayer], false );
819
820 // if cfg->m_UseStackupColors is set, board colors cannot be modified locally, but
821 // other colors can be
822 if( isStackupColorLayer3D( setting->m_Id ) && cfg )
823 setting->m_Ctl_color->SetReadOnly( cfg->m_UseStackupColors );
824 }
825 }
826
827 if( cfg )
828 {
831 }
832}
833
834
836{
837 m_presetsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ),
839
840 m_cbLayerPresets->Clear();
841
842 // Build the layers preset list.
843
844 m_cbLayerPresets->Append( _( "Follow PCB Editor" ) );
845 m_cbLayerPresets->Append( _( "Follow PCB Plot Settings" ) );
846
847 if( !m_frame->GetAdapter().m_Cfg->m_LayerPresets.empty() )
848 m_cbLayerPresets->Append( wxT( "---" ) );
849
850 for( const LAYER_PRESET_3D& preset : m_frame->GetAdapter().m_Cfg->m_LayerPresets )
851 m_cbLayerPresets->Append( preset.name );
852
853 m_cbLayerPresets->Append( wxT( "---" ) );
854 m_cbLayerPresets->Append( _( "Save preset..." ) );
855 m_cbLayerPresets->Append( _( "Delete preset..." ) );
856
857 if( aReset )
858 updateLayerPresetWidget( m_frame->GetAdapter().m_Cfg->m_CurrentPreset );
859}
860
861
863{
864 m_frame->GetAdapter().m_Cfg->m_CurrentPreset = wxEmptyString;
865
866 std::vector<LAYER_PRESET_3D>& presets = m_frame->GetAdapter().m_Cfg->m_LayerPresets;
867 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
868 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
869
870 auto it = std::find_if(
871 presets.begin(), presets.end(),
872 [&]( const LAYER_PRESET_3D& aPreset )
873 {
874 if( aPreset.name.Lower() == _( "legacy colors" ) && m_cbUseBoardStackupColors->GetValue() )
875 return false;
876
877 for( int layer = LAYER_3D_BOARD; layer < LAYER_3D_END; ++layer )
878 {
879 if( aPreset.layers.test( layer ) != visibleLayers.test( layer ) )
880 return false;
881 }
882
883 for( int layer : { LAYER_FP_REFERENCES, LAYER_FP_VALUES, LAYER_FP_TEXT } )
884 {
885 if( aPreset.layers.test( layer ) != visibleLayers.test( layer ) )
886 return false;
887 }
888
889 for( int layer = LAYER_3D_START + 1; layer < LAYER_3D_END; ++layer )
890 {
891 auto it1 = aPreset.colors.find( layer );
892 auto it2 = colors.find( layer );
893
894 if( it1 != aPreset.colors.end() && it2 != colors.end() && *it1 != *it2 )
895 return false;
896 }
897
898 return true;
899 } );
900
901 if( it != presets.end() )
902 {
903 m_frame->GetAdapter().m_Cfg->m_CurrentPreset = it->name;
904 m_cbLayerPresets->SetStringSelection( it->name );
905 }
906 else
907 {
908 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
909 }
910}
911
912
914{
915 if( aName == FOLLOW_PCB )
916 m_cbLayerPresets->SetSelection( 0 );
917 else if( aName == FOLLOW_PLOT_SETTINGS )
918 m_cbLayerPresets->SetSelection( 1 );
919 else if( !m_cbLayerPresets->SetStringSelection( aName ) )
920 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
921}
922
923
925{
926 EDA_3D_VIEWER_SETTINGS* cfg = m_frame->GetAdapter().m_Cfg;
927 int count = m_cbLayerPresets->GetCount();
928 int index = m_cbLayerPresets->GetSelection();
929 wxString name;
930
931 auto resetSelection =
932 [&]()
933 {
935 };
936
937 if( index == 0 )
938 {
940 }
941 else if( index == 1 )
942 {
944 }
945 else if( index == count - 2 )
946 {
947 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Layer preset name:" ),
948 _( "Save Layer Preset" ) );
949
950 if( dlg.ShowModal() != wxID_OK )
951 {
952 resetSelection();
953 return;
954 }
955
956 std::bitset<LAYER_3D_END> visibleLayers = m_frame->GetAdapter().GetVisibleLayers();
957 std::map<int, COLOR4D> colors = m_frame->GetAdapter().GetLayerColors();
958
959 name = dlg.GetValue();
960
961 if( LAYER_PRESET_3D* preset = cfg->FindPreset( name ) )
962 {
963 if( !IsOK( wxGetTopLevelParent( this ), _( "Overwrite existing preset?" ) ) )
964 {
965 resetSelection();
966 return;
967 }
968
969 preset->layers = visibleLayers;
970 preset->colors = colors;
971 m_cbLayerPresets->SetSelection( m_cbLayerPresets->FindString( name ) );
972 }
973 else
974 {
975 cfg->m_LayerPresets.emplace_back( name, visibleLayers, colors );
977 m_cbLayerPresets->SetStringSelection( name );
978 }
979
980 cfg->m_CurrentPreset = name;
981 m_presetMRU.Insert( name, 0 );
982
983 return;
984 }
985 else if( index == count - 1 )
986 {
987 wxArrayString headers;
988 std::vector<wxArrayString> items;
989
990 headers.Add( _( "Presets" ) );
991
992 for( LAYER_PRESET_3D& preset : cfg->m_LayerPresets )
993 {
994 wxArrayString item;
995 item.Add( preset.name );
996 items.emplace_back( item );
997 }
998
999 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
1000 dlg.SetListLabel( _( "Select preset:" ) );
1001
1002 if( dlg.ShowModal() == wxID_OK )
1003 {
1004 name = dlg.GetTextSelection();
1005
1006 if( m_cbLayerPresets->FindString( name ) != wxNOT_FOUND )
1007 m_cbLayerPresets->Delete( m_cbLayerPresets->FindString( name ) );
1008
1009 std::erase_if( cfg->m_LayerPresets,
1010 [name]( const LAYER_PRESET_3D& preset )
1011 {
1012 return preset.name == name;
1013 } );
1014
1015 if( cfg->m_CurrentPreset == name )
1016 cfg->m_CurrentPreset = wxEmptyString;
1017
1018 if( m_presetMRU.Index( name ) >= 0 )
1019 m_presetMRU.Remove( name );
1020 }
1021
1022 resetSelection();
1023 return;
1024 }
1025 else if( m_cbLayerPresets->GetString( index ) == wxT( "---" ) )
1026 {
1027 // Separator: reject the selection
1028 resetSelection();
1029 return;
1030 }
1031 else
1032 {
1033 doApplyLayerPreset( m_cbLayerPresets->GetStringSelection() );
1034 }
1035
1036 // Move to front of MRU list
1037 if( m_presetMRU.Index( name ) != wxNOT_FOUND )
1038 m_presetMRU.Remove( name );
1039
1040 m_presetMRU.Insert( name, 0 );
1041
1042 passOnFocus();
1043}
1044
1045
1046void APPEARANCE_CONTROLS_3D::doApplyLayerPreset( const wxString& aPresetName )
1047{
1048 BOARD_ADAPTER& adapter = m_frame->GetAdapter();
1049
1050 if( aPresetName == FOLLOW_PCB || aPresetName == FOLLOW_PLOT_SETTINGS )
1051 {
1052 adapter.m_Cfg->m_CurrentPreset = aPresetName;
1053 adapter.SetVisibleLayers( adapter.GetVisibleLayers() );
1054 }
1055 else if( LAYER_PRESET_3D* preset = adapter.m_Cfg->FindPreset( aPresetName ) )
1056 {
1057 adapter.m_Cfg->m_CurrentPreset = aPresetName;
1058 adapter.SetVisibleLayers( preset->layers );
1059 adapter.SetLayerColors( preset->colors );
1060
1061 if( preset->name.Lower() == _( "legacy colors" ) )
1062 adapter.m_Cfg->m_UseStackupColors = false;
1063 }
1064 else
1065 {
1066 return;
1067 }
1068
1070 m_frame->NewDisplay( true );
1071}
1072
1073
1075{
1076 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
1078
1079 m_cbViewports->Clear();
1080
1081 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
1082 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
1083
1084 m_cbViewports->Append( wxT( "---" ) );
1085 m_cbViewports->Append( _( "Save viewport..." ) );
1086 m_cbViewports->Append( _( "Delete viewport..." ) );
1087
1088 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
1089 m_lastSelectedViewport = nullptr;
1090}
1091
1092
1093void APPEARANCE_CONTROLS_3D::onViewportChanged( wxCommandEvent& aEvent )
1094{
1095 int count = m_cbViewports->GetCount();
1096 int index = m_cbViewports->GetSelection();
1097
1098 if( index >= 0 && index < count - 3 )
1099 {
1100 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
1101
1102 wxCHECK( viewport, /* void */ );
1103
1104 doApplyViewport( *viewport );
1105
1106 if( !viewport->name.IsEmpty() )
1107 {
1108 if( m_viewportMRU.Index( viewport->name ) != wxNOT_FOUND )
1109 m_viewportMRU.Remove( viewport->name );
1110
1111 m_viewportMRU.Insert( viewport->name, 0 );
1112 }
1113 }
1114 else if( index == count - 2 )
1115 {
1116 // Save current state to new preset
1117 wxString name;
1118
1119 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Viewport name:" ),
1120 _( "Save Viewport" ), name );
1121
1122 if( dlg.ShowModal() != wxID_OK )
1123 {
1125 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
1126 else
1127 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
1128
1129 return;
1130 }
1131
1132 name = dlg.GetValue();
1133 bool exists = m_viewports.count( name );
1134
1135 if( !exists )
1136 {
1137 m_viewports[name] = VIEWPORT3D( name, m_frame->GetCurrentCamera().GetViewMatrix() );
1138
1139 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
1140 }
1141 else
1142 {
1143 m_viewports[name].matrix = m_frame->GetCurrentCamera().GetViewMatrix();
1144 index = m_cbViewports->FindString( name );
1145
1146 if( m_viewportMRU.Index( name ) != wxNOT_FOUND )
1147 m_viewportMRU.Remove( name );
1148 }
1149
1150 m_cbViewports->SetSelection( index );
1151 m_viewportMRU.Insert( name, 0 );
1152
1153 return;
1154 }
1155 else if( index == count - 1 )
1156 {
1157 // Delete an existing viewport
1158 wxArrayString headers;
1159 std::vector<wxArrayString> items;
1160
1161 headers.Add( _( "Viewports" ) );
1162
1163 for( std::pair<const wxString, VIEWPORT3D>& pair : m_viewports )
1164 {
1165 wxArrayString item;
1166 item.Add( pair.first );
1167 items.emplace_back( item );
1168 }
1169
1170 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
1171 dlg.SetListLabel( _( "Select viewport:" ) );
1172
1173 if( dlg.ShowModal() == wxID_OK )
1174 {
1175 wxString viewportName = dlg.GetTextSelection();
1176 int idx = m_cbViewports->FindString( viewportName );
1177
1178 if( idx != wxNOT_FOUND )
1179 {
1180 m_viewports.erase( viewportName );
1181 m_cbViewports->Delete( idx );
1182 }
1183
1184 if( m_viewportMRU.Index( viewportName ) != wxNOT_FOUND )
1185 m_viewportMRU.Remove( viewportName );
1186 }
1187
1189 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
1190 else
1191 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
1192
1193 return;
1194 }
1195
1196 passOnFocus();
1197}
1198
1199
1200void APPEARANCE_CONTROLS_3D::onUpdateViewportsCb( wxUpdateUIEvent& aEvent )
1201{
1202 int count = m_cbViewports->GetCount();
1203 int index = m_cbViewports->GetSelection();
1204
1205 if( index >= 0 && index < count - 3 )
1206 {
1207 VIEWPORT3D* viewport = static_cast<VIEWPORT3D*>( m_cbViewports->GetClientData( index ) );
1208
1209 wxCHECK( viewport, /* void */ );
1210
1211 if( m_frame->GetCurrentCamera().GetViewMatrix() != viewport->matrix )
1212 m_cbViewports->SetSelection( -1 );
1213 }
1214}
1215
1216
1218{
1219 m_frame->GetCurrentCamera().SetViewMatrix( aViewport.matrix );
1220
1221 if( m_frame->GetAdapter().m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
1222 m_frame->GetCanvas()->Request_refresh();
1223 else
1224 m_frame->GetCanvas()->RenderRaytracingRequest();
1225}
1226
1227
1229{
1230 m_focusOwner->SetFocus();
1231}
int index
const char * name
static bool isCopperLayer3D(int aLayer)
#define RR
Render Row abbreviation to reduce source width.
static constexpr int ID_HIDE_ALL_COPPER_LAYERS
static bool isStackupColorLayer3D(int aLayer)
static constexpr int ID_SHOW_ALL_COPPER_LAYERS
static constexpr int ID_HIDE_ALL_INNER_LAYERS
static constexpr int ID_SHOW_ALL_INNER_LAYERS
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
Container for an appearance setting (can control a layer class, object type, etc.)
APPEARANCE_CONTROLS_3D_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
void OnLanguageChanged(wxCommandEvent &aEvent)
GRID_BITMAP_TOGGLE_RENDERER * m_toggleGridRenderer
void onLayerPresetChanged(wxCommandEvent &aEvent) override
void updateLayerPresetWidget(const wxString &aName)
std::vector< VIEWPORT3D > GetUserViewports() const
Return a list of viewports created by the user.
void ApplyViewport(const wxString &aPresetName)
void rebuildLayerPresetsWidget(bool aReset)
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 wxString &aPresetName)
EDA_3D_VIEWER_FRAME * m_frame
void onUpdateViewportsCb(wxUpdateUIEvent &aEvent) override
void OnSetFocus(wxFocusEvent &aEvent) override
void OnLayerVisibilityChanged(int aLayer, bool isVisible)
void OnLayerContextMenu(wxContextMenuEvent &aEvent)
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)
Update the current viewports from those saved in the project file.
A checkbox control except with custom bitmaps for the checked and unchecked states.
Helper class to handle information needed to display 3D board.
void SetVisibleLayers(const std::bitset< LAYER_3D_END > &aLayers)
std::bitset< LAYER_3D_END > GetVisibleLayers() const
void SetLayerColors(const std::map< int, COLOR4D > &aColors)
EDA_3D_VIEWER_SETTINGS * m_Cfg
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
int GetCopperLayerCount() const
Definition board.cpp:1127
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:932
static const COLOR4D WHITE
Definition color4d.h:403
A simple color swatch of the kind used to set layer colors.
KIGFX::COLOR4D GetSwatchColor() const
void SetReadOnlyCallback(std::function< void()> aCallback)
Register a handler for when the user tries to interact with a read-only swatch.
int ShowModal() override
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
double GetScaleFactor() const override
Get the DPI scale from all known sources in order:
static TOOL_ACTION showNavigator
static TOOL_ACTION showNotInPosFile
static TOOL_ACTION showTHT
static TOOL_ACTION showDNP
static TOOL_ACTION showSMD
static TOOL_ACTION showVirtual
static TOOL_ACTION showBBoxes
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
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:101
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
Object to render the board using openGL.
void RebuildHitTestAsync()
Rebuild the raytracing hit-test scene in the background after a visibility change.
void Load3dModelsIfNeeded()
Load footprint models if they are not already loaded, i.e.
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:76
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition wx_panel.h:35
@ SWATCH_SMALL
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
This file is part of the common library.
#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.
PCB_LAYER_ID Map3DLayerToPCBLayer(int aLayer)
Definition layer_id.cpp:279
int MapPCBLayerTo3DLayer(PCB_LAYER_ID aLayer)
Definition layer_id.cpp:354
@ LAYER_3D_COPPER_INNER_30
Definition layer_ids.h:684
@ LAYER_3D_USER_1
Definition layer_ids.h:599
@ LAYER_3D_SOLDERMASK_TOP
Definition layer_ids.h:588
@ LAYER_3D_USER_8
Definition layer_ids.h:606
@ LAYER_3D_USER_22
Definition layer_ids.h:620
@ LAYER_3D_USER_44
Definition layer_ids.h:642
@ LAYER_3D_USER_23
Definition layer_ids.h:621
@ LAYER_3D_NAVIGATOR
Definition layer_ids.h:649
@ LAYER_3D_USER_28
Definition layer_ids.h:626
@ LAYER_3D_BOUNDING_BOXES
Definition layer_ids.h:650
@ LAYER_3D_START
Definition layer_ids.h:578
@ LAYER_3D_USER_32
Definition layer_ids.h:630
@ LAYER_3D_USER_19
Definition layer_ids.h:617
@ LAYER_3D_USER_25
Definition layer_ids.h:623
@ LAYER_3D_ADHESIVE
Definition layer_ids.h:590
@ LAYER_3D_USER_3
Definition layer_ids.h:601
@ LAYER_3D_USER_21
Definition layer_ids.h:619
@ LAYER_3D_USER_26
Definition layer_ids.h:624
@ LAYER_3D_SMD_MODELS
Definition layer_ids.h:645
@ LAYER_3D_USER_24
Definition layer_ids.h:622
@ LAYER_3D_USER_43
Definition layer_ids.h:641
@ LAYER_3D_BACKGROUND_TOP
Definition layer_ids.h:581
@ LAYER_3D_USER_COMMENTS
Definition layer_ids.h:591
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition layer_ids.h:587
@ LAYER_3D_USER_11
Definition layer_ids.h:609
@ LAYER_3D_USER_41
Definition layer_ids.h:639
@ LAYER_3D_USER_17
Definition layer_ids.h:615
@ LAYER_3D_BOARD
Definition layer_ids.h:582
@ LAYER_3D_PLATED_BARRELS
Definition layer_ids.h:652
@ LAYER_3D_USER_ECO1
Definition layer_ids.h:593
@ LAYER_3D_COPPER_INNER_1
Definition layer_ids.h:655
@ LAYER_3D_USER_20
Definition layer_ids.h:618
@ LAYER_3D_USER_31
Definition layer_ids.h:629
@ LAYER_3D_USER_ECO2
Definition layer_ids.h:594
@ LAYER_3D_TH_MODELS
Definition layer_ids.h:644
@ LAYER_3D_B_FAB
Definition layer_ids.h:596
@ LAYER_3D_USER_15
Definition layer_ids.h:613
@ LAYER_3D_USER_38
Definition layer_ids.h:636
@ LAYER_3D_USER_13
Definition layer_ids.h:611
@ LAYER_3D_USER_33
Definition layer_ids.h:631
@ LAYER_3D_USER_35
Definition layer_ids.h:633
@ LAYER_3D_USER_29
Definition layer_ids.h:627
@ LAYER_3D_USER_40
Definition layer_ids.h:638
@ LAYER_3D_SILKSCREEN_TOP
Definition layer_ids.h:586
@ LAYER_3D_B_COURTYARD
Definition layer_ids.h:598
@ LAYER_3D_VIRTUAL_MODELS
Definition layer_ids.h:646
@ LAYER_3D_MODELS_MARKED_DNP
Definition layer_ids.h:648
@ LAYER_3D_USER_7
Definition layer_ids.h:605
@ LAYER_3D_COPPER_TOP
Definition layer_ids.h:583
@ LAYER_3D_USER_12
Definition layer_ids.h:610
@ LAYER_3D_SOLDERPASTE
Definition layer_ids.h:589
@ LAYER_3D_USER_30
Definition layer_ids.h:628
@ LAYER_3D_USER_36
Definition layer_ids.h:634
@ LAYER_3D_USER_2
Definition layer_ids.h:600
@ LAYER_3D_USER_18
Definition layer_ids.h:616
@ LAYER_3D_OFF_BOARD_SILK
Definition layer_ids.h:651
@ LAYER_3D_USER_14
Definition layer_ids.h:612
@ LAYER_3D_USER_5
Definition layer_ids.h:603
@ LAYER_3D_USER_37
Definition layer_ids.h:635
@ LAYER_3D_USER_10
Definition layer_ids.h:608
@ LAYER_3D_MODELS_NOT_IN_POS
Definition layer_ids.h:647
@ LAYER_3D_USER_42
Definition layer_ids.h:640
@ LAYER_3D_USER_45
Definition layer_ids.h:643
@ LAYER_3D_USER_6
Definition layer_ids.h:604
@ LAYER_3D_USER_4
Definition layer_ids.h:602
@ LAYER_3D_USER_27
Definition layer_ids.h:625
@ LAYER_3D_USER_DRAWINGS
Definition layer_ids.h:592
@ LAYER_3D_COPPER_BOTTOM
Definition layer_ids.h:584
@ LAYER_3D_USER_39
Definition layer_ids.h:637
@ LAYER_3D_USER_9
Definition layer_ids.h:607
@ LAYER_3D_BACKGROUND_BOTTOM
Definition layer_ids.h:580
@ LAYER_3D_USER_16
Definition layer_ids.h:614
@ LAYER_3D_SILKSCREEN_BOTTOM
Definition layer_ids.h:585
@ LAYER_3D_F_COURTYARD
Definition layer_ids.h:597
@ LAYER_3D_USER_34
Definition layer_ids.h:632
@ LAYER_3D_END
Definition layer_ids.h:686
@ LAYER_3D_F_FAB
Definition layer_ids.h:595
@ LAYER_FP_REFERENCES
Show footprints references (when texts are visible).
Definition layer_ids.h:262
@ LAYER_FP_TEXT
Definition layer_ids.h:236
@ LAYER_FP_VALUES
Show footprints values (when texts are visible).
Definition layer_ids.h:259
bool IsInnerCopperLayer(int aLayerId)
Test whether a layer is an inner (In1_Cu to In30_Cu) copper layer.
Definition layer_ids.h:763
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Cu
Definition layer_ids.h:61
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ F_Cu
Definition layer_ids.h:60
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
const int c_IndicatorSizeDIP
Definition ui_common.h:53
#define _HKI(x)
Definition page_info.cpp:40
see class PGM_BASE
static bool isCopper(const PNS::ITEM *aItem)
wxString name
A name for this layer set.