From f45760062b6cf88cd5265736413c4aad005a6d3e Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 11 Aug 2023 18:40:13 +0100 Subject: [PATCH] ADDED: appearances manager for 3D viewer. Fixes https://gitlab.com/kicad/code/kicad/-/issues/12413 --- 3d-viewer/3d_canvas/board_adapter.cpp | 350 +++++-- 3d-viewer/3d_canvas/board_adapter.h | 24 +- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 22 +- 3d-viewer/3d_canvas/create_layer_items.cpp | 16 +- .../3d_rendering/opengl/create_scene.cpp | 8 +- .../3d_rendering/opengl/render_3d_opengl.cpp | 45 +- .../3d_rendering/raytracing/create_scene.cpp | 38 +- 3d-viewer/3d_viewer/3d_menubar.cpp | 10 +- 3d-viewer/3d_viewer/3d_toolbar.cpp | 39 +- 3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp | 359 +++----- 3d-viewer/3d_viewer/eda_3d_viewer_frame.h | 30 +- .../3d_viewer/eda_3d_viewer_settings.cpp | 246 ++++- 3d-viewer/3d_viewer/eda_3d_viewer_settings.h | 69 +- 3d-viewer/3d_viewer/tools/eda_3d_actions.cpp | 82 +- 3d-viewer/3d_viewer/tools/eda_3d_actions.h | 14 +- .../3d_viewer/tools/eda_3d_controller.cpp | 149 +-- 3d-viewer/3d_viewer/tools/eda_3d_controller.h | 4 +- 3d-viewer/CMakeLists.txt | 29 +- 3d-viewer/dialogs/appearance_controls_3D.cpp | 864 ++++++++++++++++++ 3d-viewer/dialogs/appearance_controls_3D.h | 158 ++++ .../dialogs/appearance_controls_3D_base.cpp | 95 ++ .../dialogs/appearance_controls_3D_base.fbp | 487 ++++++++++ .../dialogs/appearance_controls_3D_base.h | 60 ++ 3d-viewer/dialogs/panel_3D_colors.cpp | 11 +- .../dialogs/panel_3D_display_options.cpp | 54 +- .../dialogs/panel_3D_display_options_base.cpp | 12 +- .../dialogs/panel_3D_display_options_base.fbp | 10 +- .../dialogs/panel_3D_display_options_base.h | 2 +- 3d-viewer/dialogs/panel_preview_3d_model.cpp | 32 +- common/dialogs/eda_view_switcher.cpp | 3 +- common/settings/builtin_color_themes.h | 4 +- common/settings/color_settings.cpp | 2 +- common/widgets/bitmap_toggle.cpp | 2 +- include/eda_base_frame.h | 41 +- include/layer_ids.h | 17 +- pcbnew/pcb_base_edit_frame.cpp | 6 + pcbnew/widgets/appearance_controls.cpp | 40 +- 37 files changed, 2743 insertions(+), 691 deletions(-) create mode 100644 3d-viewer/dialogs/appearance_controls_3D.cpp create mode 100644 3d-viewer/dialogs/appearance_controls_3D.h create mode 100644 3d-viewer/dialogs/appearance_controls_3D_base.cpp create mode 100644 3d-viewer/dialogs/appearance_controls_3D_base.fbp create mode 100644 3d-viewer/dialogs/appearance_controls_3D_base.h diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp index ddcb386f82..0540e7898e 100644 --- a/3d-viewer/3d_canvas/board_adapter.cpp +++ b/3d-viewer/3d_canvas/board_adapter.cpp @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2022 Mario Luzeiro + * Copyright (C) 2023 CERN * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or @@ -49,7 +50,7 @@ #define SOLDERPASTE_LAYER_THICKNESS pcbIUScale.mmToIU( 0.04 ) -CUSTOM_COLORS_LIST BOARD_ADAPTER::g_SilkscreenColors; +CUSTOM_COLORS_LIST BOARD_ADAPTER::g_SilkColors; CUSTOM_COLORS_LIST BOARD_ADAPTER::g_MaskColors; CUSTOM_COLORS_LIST BOARD_ADAPTER::g_PasteColors; CUSTOM_COLORS_LIST BOARD_ADAPTER::g_FinishColors; @@ -62,6 +63,8 @@ KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSolderMask; KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSolderPaste; KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSurfaceFinish; KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultBoardBody; +KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultComments; +KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultECOs; // To be used in Raytracing render to create bevels on layer items float g_BevelThickness3DU = 0.0f; @@ -130,6 +133,10 @@ BOARD_ADAPTER::BOARD_ADAPTER() : m_SilkScreenColorTop = SFVEC4F( 0.9, 0.9, 0.9, 1.0 ); m_SilkScreenColorBot = SFVEC4F( 0.9, 0.9, 0.9, 1.0 ); m_CopperColor = SFVEC4F( 0.75, 0.61, 0.23, 1.0 ); + m_UserDrawingsColor = SFVEC4F( 0.85, 0.85, 0.85, 1.0 ); + m_UserCommentsColor = SFVEC4F( 0.85, 0.85, 0.85, 1.0 ); + m_ECO1Color = SFVEC4F( 0.70, 0.10, 0.10, 1.0 ); + m_ECO2Color = SFVEC4F( 0.70, 0.10, 0.10, 1.0 ); m_platedPadsFront = nullptr; m_platedPadsBack = nullptr; @@ -142,14 +149,14 @@ BOARD_ADAPTER::BOARD_ADAPTER() : #define ADD_COLOR( list, r, g, b, a, name ) \ list.emplace_back( r/255.0, g/255.0, b/255.0, a, name ) - ADD_COLOR( g_SilkscreenColors, 245, 245, 245, 1.0, NotSpecifiedPrm() ); // White - ADD_COLOR( g_SilkscreenColors, 20, 51, 36, 1.0, wxT( "Green" ) ); - ADD_COLOR( g_SilkscreenColors, 181, 19, 21, 1.0, wxT( "Red" ) ); - ADD_COLOR( g_SilkscreenColors, 2, 59, 162, 1.0, wxT( "Blue" ) ); - ADD_COLOR( g_SilkscreenColors, 11, 11, 11, 1.0, wxT( "Black" ) ); - ADD_COLOR( g_SilkscreenColors, 245, 245, 245, 1.0, wxT( "White" ) ); - ADD_COLOR( g_SilkscreenColors, 32, 2, 53, 1.0, wxT( "Purple" ) ); - ADD_COLOR( g_SilkscreenColors, 194, 195, 0, 1.0, wxT( "Yellow" ) ); + ADD_COLOR( g_SilkColors, 245, 245, 245, 1.0, NotSpecifiedPrm() ); // White + ADD_COLOR( g_SilkColors, 20, 51, 36, 1.0, wxT( "Green" ) ); + ADD_COLOR( g_SilkColors, 181, 19, 21, 1.0, wxT( "Red" ) ); + ADD_COLOR( g_SilkColors, 2, 59, 162, 1.0, wxT( "Blue" ) ); + ADD_COLOR( g_SilkColors, 11, 11, 11, 1.0, wxT( "Black" ) ); + ADD_COLOR( g_SilkColors, 245, 245, 245, 1.0, wxT( "White" ) ); + ADD_COLOR( g_SilkColors, 32, 2, 53, 1.0, wxT( "Purple" ) ); + ADD_COLOR( g_SilkColors, 194, 195, 0, 1.0, wxT( "Yellow" ) ); ADD_COLOR( g_MaskColors, 20, 51, 36, 0.83, NotSpecifiedPrm() ); // Green ADD_COLOR( g_MaskColors, 20, 51, 36, 0.83, wxT( "Green" ) ); @@ -196,6 +203,9 @@ BOARD_ADAPTER::BOARD_ADAPTER() : g_DefaultSurfaceFinish = COLOR4D( 0.75, 0.61, 0.23, 1.0 ); g_DefaultBoardBody = COLOR4D( 0.43, 0.45, 0.30, 0.90 ); + g_DefaultComments = COLOR4D( 0.85, 0.85, 0.85, 1.0 ); + g_DefaultECOs = COLOR4D( 0.70, 0.10, 0.10, 1.0 ); + g_ColorsLoaded = true; } #undef ADD_COLOR @@ -217,55 +227,33 @@ void BOARD_ADAPTER::ReloadColorSettings() noexcept } -bool BOARD_ADAPTER::Is3dLayerEnabled( PCB_LAYER_ID aLayer ) const +bool BOARD_ADAPTER::Is3dLayerEnabled( PCB_LAYER_ID aLayer, + const std::bitset& aVisibilityFlags ) const { wxASSERT( aLayer < PCB_LAYER_ID_COUNT ); if( m_board && !m_board->IsLayerEnabled( aLayer ) ) return false; - // see if layer needs to be shown - // check the flags switch( aLayer ) { - case B_Adhes: - case F_Adhes: - return m_Cfg->m_Render.show_adhesive; - - case B_Paste: - case F_Paste: - return m_Cfg->m_Render.show_solderpaste; - - case B_SilkS: - case F_SilkS: - return m_Cfg->m_Render.show_silkscreen; - - case B_Mask: - case F_Mask: - return m_Cfg->m_Render.show_soldermask; - - case Dwgs_User: - case Cmts_User: - return !m_Cfg->m_Render.realistic && m_Cfg->m_Render.show_comments; - - case Eco1_User: - case Eco2_User: - return !m_Cfg->m_Render.realistic && m_Cfg->m_Render.show_eco; - - case Edge_Cuts: - return !m_Cfg->m_Render.realistic && !m_Cfg->m_Render.show_board_body; - - case Margin: - return !m_Cfg->m_Render.realistic; - - case B_Cu: - case F_Cu: - return !m_board || m_board->IsLayerVisible( aLayer ) || m_Cfg->m_Render.realistic - || m_board->IsFootprintHolder(); - - default: - // the layer is an internal copper layer, used the visibility - return m_board && m_board->IsLayerVisible( aLayer ); + case B_Cu: return aVisibilityFlags.test( LAYER_3D_COPPER_BOTTOM ); + case F_Cu: return aVisibilityFlags.test( LAYER_3D_COPPER_TOP ); + case B_Adhes: return aVisibilityFlags.test( LAYER_3D_ADHESIVE ); + case F_Adhes: return aVisibilityFlags.test( LAYER_3D_ADHESIVE ); + case B_Paste: return aVisibilityFlags.test( LAYER_3D_SOLDERPASTE ); + case F_Paste: return aVisibilityFlags.test( LAYER_3D_SOLDERPASTE ); + case B_SilkS: return aVisibilityFlags.test( LAYER_3D_SILKSCREEN_BOTTOM ); + case F_SilkS: return aVisibilityFlags.test( LAYER_3D_SILKSCREEN_TOP ); + case B_Mask: return aVisibilityFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ); + case F_Mask: return aVisibilityFlags.test( LAYER_3D_SOLDERMASK_TOP ); + case Dwgs_User: return aVisibilityFlags.test( LAYER_3D_USER_DRAWINGS ); + case Cmts_User: return aVisibilityFlags.test( LAYER_3D_USER_COMMENTS ); + case Eco1_User: return aVisibilityFlags.test( LAYER_3D_USER_ECO1 ); + case Eco2_User: return aVisibilityFlags.test( LAYER_3D_USER_ECO2 ); + case Edge_Cuts: return !m_Cfg->m_Render.realistic && !m_Cfg->m_Render.show_board_body; + case Margin: return !m_Cfg->m_Render.realistic; + default: return m_board && m_board->IsLayerVisible( aLayer ); } } @@ -537,22 +525,66 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR createLayers( aStatusReporter ); - COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings(); - auto to_SFVEC4F = []( const COLOR4D& src ) { return SFVEC4F( src.r, src.g, src.b, src.a ); }; - m_BgColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_BACKGROUND_TOP ) ); - m_BgColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_BACKGROUND_BOTTOM ) ); + std::map colors = GetLayerColors(); - m_SolderPasteColor = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERPASTE ) ); + m_BgColorTop = to_SFVEC4F( colors[ LAYER_3D_BACKGROUND_TOP ] ); + m_BgColorBot = to_SFVEC4F( colors[ LAYER_3D_BACKGROUND_BOTTOM ] ); + m_SolderPasteColor = to_SFVEC4F( colors[ LAYER_3D_SOLDERPASTE ] ); + m_SilkScreenColorBot = to_SFVEC4F( colors[ LAYER_3D_SILKSCREEN_BOTTOM ] ); + m_SilkScreenColorTop = to_SFVEC4F( colors[ LAYER_3D_SILKSCREEN_TOP ] ); + m_SolderMaskColorBot = to_SFVEC4F( colors[ LAYER_3D_SOLDERMASK_BOTTOM ] ); + m_SolderMaskColorTop = to_SFVEC4F( colors[ LAYER_3D_SOLDERMASK_TOP ] ); + m_CopperColor = to_SFVEC4F( colors[ LAYER_3D_COPPER_TOP ] ); + m_BoardBodyColor = to_SFVEC4F( colors[ LAYER_3D_BOARD ] ); + m_UserDrawingsColor = to_SFVEC4F( colors[ LAYER_3D_USER_DRAWINGS ] ); + m_UserCommentsColor = to_SFVEC4F( colors[ LAYER_3D_USER_COMMENTS ] ); + m_ECO1Color = to_SFVEC4F( colors[ LAYER_3D_USER_ECO1 ] ); + m_ECO2Color = to_SFVEC4F( colors[ LAYER_3D_USER_ECO2 ] ); +} - if( m_board && colors->GetUseBoardStackupColors() ) + +std::map BOARD_ADAPTER::GetDefaultColors() const +{ + std::map colors; + + colors[ LAYER_3D_BACKGROUND_TOP ] = BOARD_ADAPTER::g_DefaultBackgroundTop; + colors[ LAYER_3D_BACKGROUND_BOTTOM ] = BOARD_ADAPTER::g_DefaultBackgroundBot; + colors[ LAYER_3D_BOARD ] = BOARD_ADAPTER::g_DefaultBoardBody; + colors[ LAYER_3D_COPPER_TOP ] = BOARD_ADAPTER::g_DefaultSurfaceFinish; + colors[ LAYER_3D_COPPER_BOTTOM ] = BOARD_ADAPTER::g_DefaultSurfaceFinish; + colors[ LAYER_3D_SILKSCREEN_TOP ] = BOARD_ADAPTER::g_DefaultSilkscreen; + colors[ LAYER_3D_SILKSCREEN_BOTTOM ] = BOARD_ADAPTER::g_DefaultSilkscreen; + colors[ LAYER_3D_SOLDERMASK_TOP ] = BOARD_ADAPTER::g_DefaultSolderMask; + colors[ LAYER_3D_SOLDERMASK_BOTTOM ] = BOARD_ADAPTER::g_DefaultSolderMask; + colors[ LAYER_3D_SOLDERPASTE ] = BOARD_ADAPTER::g_DefaultSolderPaste; + colors[ LAYER_3D_USER_DRAWINGS ] = BOARD_ADAPTER::g_DefaultComments; + colors[ LAYER_3D_USER_COMMENTS ] = BOARD_ADAPTER::g_DefaultComments; + colors[ LAYER_3D_USER_ECO1 ] = BOARD_ADAPTER::g_DefaultECOs; + colors[ LAYER_3D_USER_ECO2 ] = BOARD_ADAPTER::g_DefaultECOs; + + return colors; +} + + +std::map BOARD_ADAPTER::GetLayerColors() const +{ + std::map colors; + + if( m_Cfg->m_CurrentPreset == FOLLOW_PCB || m_Cfg->m_CurrentPreset == FOLLOW_PLOT_SETTINGS ) { + colors = GetDefaultColors(); + + if( !m_board ) + return colors; + const BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor(); + KIGFX::COLOR4D bodyColor( 0, 0, 0, 0 ); auto findColor = []( const wxString& aColorName, const CUSTOM_COLORS_LIST& aColorSet ) @@ -573,13 +605,6 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR return KIGFX::COLOR4D(); }; - m_SilkScreenColorTop = to_SFVEC4F( g_DefaultSilkscreen ); - m_SilkScreenColorBot = to_SFVEC4F( g_DefaultSilkscreen ); - m_SolderMaskColorTop = to_SFVEC4F( g_DefaultSolderMask ); - m_SolderMaskColorBot = to_SFVEC4F( g_DefaultSolderMask ); - - KIGFX::COLOR4D bodyColor( 0, 0, 0, 0 ); - for( const BOARD_STACKUP_ITEM* stackupItem : stackup.GetList() ) { wxString colorName = stackupItem->GetColor(); @@ -588,16 +613,17 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR { case BS_ITEM_TYPE_SILKSCREEN: if( stackupItem->GetBrdLayerId() == F_SilkS ) - m_SilkScreenColorTop = to_SFVEC4F( findColor( colorName, g_SilkscreenColors ) ); + colors[ LAYER_3D_SILKSCREEN_TOP ] = findColor( colorName, g_SilkColors ); else - m_SilkScreenColorBot = to_SFVEC4F( findColor( colorName, g_SilkscreenColors ) ); + colors[ LAYER_3D_SILKSCREEN_BOTTOM ] = findColor( colorName, g_SilkColors ); + break; case BS_ITEM_TYPE_SOLDERMASK: if( stackupItem->GetBrdLayerId() == F_Mask ) - m_SolderMaskColorTop = to_SFVEC4F( findColor( colorName, g_MaskColors ) ); + colors[ LAYER_3D_SOLDERMASK_TOP ] = findColor( colorName, g_MaskColors ); else - m_SolderMaskColorBot = to_SFVEC4F( findColor( colorName, g_MaskColors ) ); + colors[ LAYER_3D_SOLDERMASK_BOTTOM ] = findColor( colorName, g_MaskColors ); break; @@ -620,46 +646,202 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR } if( bodyColor != COLOR4D( 0, 0, 0, 0 ) ) - m_BoardBodyColor = to_SFVEC4F( bodyColor ); - else - m_BoardBodyColor = to_SFVEC4F( g_DefaultBoardBody ); + colors[ LAYER_3D_BOARD ] = bodyColor; const wxString& finishName = stackup.m_FinishType; if( finishName.EndsWith( wxT( "OSP" ) ) ) { - m_CopperColor = to_SFVEC4F( findColor( wxT( "Copper" ), g_FinishColors ) ); + colors[ LAYER_3D_COPPER_TOP ] = findColor( wxT( "Copper" ), g_FinishColors ); } else if( finishName.EndsWith( wxT( "IG" ) ) || finishName.EndsWith( wxT( "gold" ) ) ) { - m_CopperColor = to_SFVEC4F( findColor( wxT( "Gold" ), g_FinishColors ) ); + colors[ LAYER_3D_COPPER_TOP ] = findColor( wxT( "Gold" ), g_FinishColors ); } else if( finishName.StartsWith( wxT( "HAL" ) ) || finishName.StartsWith( wxT( "HASL" ) ) || finishName.EndsWith( wxT( "tin" ) ) || finishName.EndsWith( wxT( "nickel" ) ) ) { - m_CopperColor = to_SFVEC4F( findColor( wxT( "Tin" ), g_FinishColors ) ); + colors[ LAYER_3D_COPPER_TOP ] = findColor( wxT( "Tin" ), g_FinishColors ); } else if( finishName.EndsWith( wxT( "silver" ) ) ) { - m_CopperColor = to_SFVEC4F( findColor( wxT( "Silver" ), g_FinishColors ) ); - } - else - { - m_CopperColor = to_SFVEC4F( g_DefaultSurfaceFinish ); + colors[ LAYER_3D_COPPER_TOP ] = findColor( wxT( "Silver" ), g_FinishColors ); } + + SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager(); + PCBNEW_SETTINGS* pcbnewSettings = mgr.GetAppSettings(); + COLOR_SETTINGS* pcbnewColors = mgr.GetColorSettings( pcbnewSettings->m_ColorTheme ); + + colors[ LAYER_3D_USER_DRAWINGS ] = pcbnewColors->GetColor( Dwgs_User ); + colors[ LAYER_3D_USER_COMMENTS ] = pcbnewColors->GetColor( Cmts_User ); + colors[ LAYER_3D_USER_ECO1 ] = pcbnewColors->GetColor( Eco1_User ); + colors[ LAYER_3D_USER_ECO2 ] = pcbnewColors->GetColor( Eco2_User ); + } + else if( LAYER_PRESET_3D* preset = m_Cfg->FindPreset( m_Cfg->m_CurrentPreset ) ) + { + return preset->colors; } else { - m_SilkScreenColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_SILKSCREEN_BOTTOM ) ); - m_SilkScreenColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_SILKSCREEN_TOP ) ); - m_SolderMaskColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERMASK_BOTTOM ) ); - m_SolderMaskColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERMASK_TOP ) ); - m_CopperColor = to_SFVEC4F( colors->GetColor( LAYER_3D_COPPER ) ); - m_BoardBodyColor = to_SFVEC4F( colors->GetColor( LAYER_3D_BOARD ) ); + COLOR_SETTINGS* settings = Pgm().GetSettingsManager().GetColorSettings(); + + for( const auto& [ layer, color ] : GetDefaultColors() ) + colors[ layer ] = settings->GetColor( layer ); } + + colors[ LAYER_3D_COPPER_BOTTOM ] = colors[ LAYER_3D_COPPER_TOP ]; + return colors; +} + + +void BOARD_ADAPTER::SetLayerColors( const std::map& aColors ) +{ + COLOR_SETTINGS* settings = Pgm().GetSettingsManager().GetColorSettings(); + + for( const auto& [ layer, color ] : aColors ) + settings->SetColor( layer, color ); +} + + +void BOARD_ADAPTER::SetVisibleLayers( const std::bitset& aLayers ) +{ + m_Cfg->m_Render.show_board_body = aLayers.test( LAYER_3D_BOARD ); + m_Cfg->m_Render.show_copper_top = aLayers.test( LAYER_3D_COPPER_TOP ); + m_Cfg->m_Render.show_copper_bottom = aLayers.test( LAYER_3D_COPPER_BOTTOM ); + m_Cfg->m_Render.show_silkscreen_top = aLayers.test( LAYER_3D_SILKSCREEN_TOP ); + m_Cfg->m_Render.show_silkscreen_bottom = aLayers.test( LAYER_3D_SILKSCREEN_BOTTOM ); + m_Cfg->m_Render.show_soldermask_top = aLayers.test( LAYER_3D_SOLDERMASK_TOP ); + m_Cfg->m_Render.show_soldermask_bottom = aLayers.test( LAYER_3D_SOLDERMASK_BOTTOM ); + m_Cfg->m_Render.show_solderpaste = aLayers.test( LAYER_3D_SOLDERPASTE ); + m_Cfg->m_Render.show_adhesive = aLayers.test( LAYER_3D_ADHESIVE ); + m_Cfg->m_Render.show_comments = aLayers.test( LAYER_3D_USER_COMMENTS ); + m_Cfg->m_Render.show_drawings = aLayers.test( LAYER_3D_USER_DRAWINGS ); + m_Cfg->m_Render.show_eco1 = aLayers.test( LAYER_3D_USER_ECO1 ); + m_Cfg->m_Render.show_eco2 = aLayers.test( LAYER_3D_USER_ECO2 ); + + m_Cfg->m_Render.show_footprints_normal = aLayers.test( LAYER_3D_TH_MODELS ); + m_Cfg->m_Render.show_footprints_insert = aLayers.test( LAYER_3D_SMD_MODELS ); + m_Cfg->m_Render.show_footprints_virtual = aLayers.test( LAYER_3D_VIRTUAL_MODELS ); + m_Cfg->m_Render.show_footprints_not_in_posfile = aLayers.test( LAYER_3D_MODELS_NOT_IN_POS ); + m_Cfg->m_Render.show_footprints_dnp = aLayers.test( LAYER_3D_MODELS_MARKED_DNP ); + + m_Cfg->m_Render.show_fp_references = aLayers.test( LAYER_FP_REFERENCES ); + m_Cfg->m_Render.show_fp_values = aLayers.test( LAYER_FP_VALUES ); + m_Cfg->m_Render.show_fp_text = aLayers.test( LAYER_FP_TEXT ); + + m_Cfg->m_Render.opengl_show_model_bbox = aLayers.test( LAYER_3D_BOUNDING_BOXES ); + m_Cfg->m_Render.show_axis = aLayers.test( LAYER_3D_AXES ); +} + + +std::bitset BOARD_ADAPTER::GetVisibleLayers() const +{ + std::bitset ret; + + ret.set( LAYER_3D_BOARD, m_Cfg->m_Render.show_board_body ); + ret.set( LAYER_3D_COPPER_TOP, m_Cfg->m_Render.show_copper_top ); + ret.set( LAYER_3D_COPPER_BOTTOM, m_Cfg->m_Render.show_copper_bottom ); + ret.set( LAYER_3D_SILKSCREEN_TOP, m_Cfg->m_Render.show_silkscreen_top ); + ret.set( LAYER_3D_SILKSCREEN_BOTTOM, m_Cfg->m_Render.show_silkscreen_bottom ); + ret.set( LAYER_3D_SOLDERMASK_TOP, m_Cfg->m_Render.show_soldermask_top ); + ret.set( LAYER_3D_SOLDERMASK_BOTTOM, m_Cfg->m_Render.show_soldermask_bottom ); + ret.set( LAYER_3D_SOLDERPASTE, m_Cfg->m_Render.show_solderpaste ); + ret.set( LAYER_3D_ADHESIVE, m_Cfg->m_Render.show_adhesive ); + ret.set( LAYER_3D_USER_COMMENTS, m_Cfg->m_Render.show_comments ); + ret.set( LAYER_3D_USER_DRAWINGS, m_Cfg->m_Render.show_drawings ); + ret.set( LAYER_3D_USER_ECO1, m_Cfg->m_Render.show_eco1 ); + ret.set( LAYER_3D_USER_ECO2, m_Cfg->m_Render.show_eco2 ); + + ret.set( LAYER_FP_REFERENCES, m_Cfg->m_Render.show_fp_references ); + ret.set( LAYER_FP_VALUES, m_Cfg->m_Render.show_fp_values ); + ret.set( LAYER_FP_TEXT, m_Cfg->m_Render.show_fp_text ); + + ret.set( LAYER_3D_TH_MODELS, m_Cfg->m_Render.show_footprints_normal ); + ret.set( LAYER_3D_SMD_MODELS, m_Cfg->m_Render.show_footprints_insert ); + ret.set( LAYER_3D_VIRTUAL_MODELS, m_Cfg->m_Render.show_footprints_virtual ); + ret.set( LAYER_3D_MODELS_NOT_IN_POS, m_Cfg->m_Render.show_footprints_not_in_posfile ); + ret.set( LAYER_3D_MODELS_MARKED_DNP, m_Cfg->m_Render.show_footprints_dnp ); + + ret.set( LAYER_3D_BOUNDING_BOXES, m_Cfg->m_Render.opengl_show_model_bbox ); + ret.set( LAYER_3D_AXES, m_Cfg->m_Render.show_axis ); + + if( m_Cfg->m_CurrentPreset == FOLLOW_PCB ) + { + if( !m_board ) + return ret; + + ret.set( LAYER_3D_BOARD, m_board->IsLayerVisible( Edge_Cuts ) ); + ret.set( LAYER_3D_COPPER_TOP, m_board->IsLayerVisible( F_Cu ) ); + ret.set( LAYER_3D_COPPER_BOTTOM, m_board->IsLayerVisible( B_Cu ) ); + ret.set( LAYER_3D_SILKSCREEN_TOP, m_board->IsLayerVisible( F_SilkS ) ); + ret.set( LAYER_3D_SILKSCREEN_BOTTOM, m_board->IsLayerVisible( B_SilkS ) ); + ret.set( LAYER_3D_SOLDERMASK_TOP, m_board->IsLayerVisible( F_Mask ) ); + ret.set( LAYER_3D_SOLDERMASK_BOTTOM, m_board->IsLayerVisible( B_Mask ) ); + ret.set( LAYER_3D_SOLDERPASTE, m_board->IsLayerVisible( F_Paste ) ); + ret.set( LAYER_3D_ADHESIVE, m_board->IsLayerVisible( F_Adhes ) ); + ret.set( LAYER_3D_USER_COMMENTS, m_board->IsLayerVisible( Cmts_User ) ); + ret.set( LAYER_3D_USER_DRAWINGS, m_board->IsLayerVisible( Dwgs_User ) ); + ret.set( LAYER_3D_USER_ECO1, m_board->IsLayerVisible( Eco1_User ) ); + ret.set( LAYER_3D_USER_ECO2, m_board->IsLayerVisible( Eco2_User ) ); + + for( GAL_LAYER_ID layer : { LAYER_FP_REFERENCES, LAYER_FP_VALUES, LAYER_FP_TEXT } ) + ret.set( layer, m_board->IsElementVisible( layer ) ); + } + else if( m_Cfg->m_CurrentPreset == FOLLOW_PLOT_SETTINGS ) + { + if( !m_board ) + return ret; + + const PCB_PLOT_PARAMS& plotParams = m_board->GetPlotOptions(); + LSET layers = plotParams.GetLayerSelection() | plotParams.GetPlotOnAllLayersSelection(); + + ret.set( LAYER_3D_BOARD, true ); + ret.set( LAYER_3D_COPPER_TOP, layers.test( F_Cu ) ); + ret.set( LAYER_3D_COPPER_BOTTOM, layers.test( B_Cu ) ); + ret.set( LAYER_3D_SILKSCREEN_TOP, layers.test( F_SilkS ) ); + ret.set( LAYER_3D_SILKSCREEN_BOTTOM, layers.test( B_SilkS ) ); + ret.set( LAYER_3D_SOLDERMASK_TOP, layers.test( F_Mask ) ); + ret.set( LAYER_3D_SOLDERMASK_BOTTOM, layers.test( B_Mask ) ); + ret.set( LAYER_3D_SOLDERPASTE, layers.test( F_Paste ) ); + ret.set( LAYER_3D_ADHESIVE, layers.test( F_Adhes ) ); + ret.set( LAYER_3D_USER_COMMENTS, layers.test( Cmts_User ) ); + ret.set( LAYER_3D_USER_DRAWINGS, layers.test( Dwgs_User ) ); + ret.set( LAYER_3D_USER_ECO1, layers.test( Eco1_User ) ); + ret.set( LAYER_3D_USER_ECO2, layers.test( Eco2_User ) ); + + ret.set( LAYER_FP_REFERENCES, plotParams.GetPlotReference() ); + ret.set( LAYER_FP_VALUES, plotParams.GetPlotValue() ); + ret.set( LAYER_FP_TEXT, true ); + } + else if( LAYER_PRESET_3D* preset = m_Cfg->FindPreset( m_Cfg->m_CurrentPreset ) ) + { + ret = preset->layers; + } + else + { + ret.set( LAYER_3D_BOARD, m_Cfg->m_Render.show_board_body ); + ret.set( LAYER_3D_COPPER_TOP, m_Cfg->m_Render.show_copper_top ); + ret.set( LAYER_3D_COPPER_BOTTOM, m_Cfg->m_Render.show_copper_bottom ); + ret.set( LAYER_3D_SILKSCREEN_TOP, m_Cfg->m_Render.show_silkscreen_top ); + ret.set( LAYER_3D_SILKSCREEN_BOTTOM, m_Cfg->m_Render.show_silkscreen_bottom ); + ret.set( LAYER_3D_SOLDERMASK_TOP, m_Cfg->m_Render.show_soldermask_top ); + ret.set( LAYER_3D_SOLDERMASK_BOTTOM, m_Cfg->m_Render.show_soldermask_bottom ); + ret.set( LAYER_3D_SOLDERPASTE, m_Cfg->m_Render.show_solderpaste ); + ret.set( LAYER_3D_ADHESIVE, m_Cfg->m_Render.show_adhesive ); + ret.set( LAYER_3D_USER_COMMENTS, m_Cfg->m_Render.show_comments ); + ret.set( LAYER_3D_USER_DRAWINGS, m_Cfg->m_Render.show_drawings ); + ret.set( LAYER_3D_USER_ECO1, m_Cfg->m_Render.show_eco1 ); + ret.set( LAYER_3D_USER_ECO2, m_Cfg->m_Render.show_eco2 ); + + ret.set( LAYER_FP_REFERENCES, m_Cfg->m_Render.show_fp_references ); + ret.set( LAYER_FP_VALUES, m_Cfg->m_Render.show_fp_values ); + ret.set( LAYER_FP_TEXT, m_Cfg->m_Render.show_fp_text ); + } + + return ret; } diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h index d47dc7b7a9..d40ac1c965 100644 --- a/3d-viewer/3d_canvas/board_adapter.h +++ b/3d-viewer/3d_canvas/board_adapter.h @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -85,7 +86,8 @@ public: * * @param aLayer layer ID to get status. */ - bool Is3dLayerEnabled( PCB_LAYER_ID aLayer ) const; + bool Is3dLayerEnabled( PCB_LAYER_ID aLayer, + const std::bitset& aVisibilityFlags ) const; /** * Test if footprint should be displayed in relation to attributes and the flags. @@ -102,6 +104,13 @@ public: void ReloadColorSettings() noexcept; + std::map GetLayerColors() const; + std::map GetDefaultColors() const; + void SetLayerColors( const std::map& aColors ); + + std::bitset GetVisibleLayers() const; + void SetVisibleLayers( const std::bitset& aLayers ); + /** * Function to be called by the render when it need to reload the settings for the board. * @@ -348,7 +357,8 @@ private: PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads ); void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer, - PCB_LAYER_ID aLayerId ); + PCB_LAYER_ID aLayerId, + const std::bitset& aVisibilityFlags ); void addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aDstContainer, const BOARD_ITEM* aOwner ); @@ -375,7 +385,7 @@ private: SHAPE_POLY_SET& aBuffer ) const; public: - static CUSTOM_COLORS_LIST g_SilkscreenColors; + static CUSTOM_COLORS_LIST g_SilkColors; static CUSTOM_COLORS_LIST g_MaskColors; static CUSTOM_COLORS_LIST g_PasteColors; static CUSTOM_COLORS_LIST g_FinishColors; @@ -388,6 +398,8 @@ public: static KIGFX::COLOR4D g_DefaultSolderPaste; static KIGFX::COLOR4D g_DefaultSurfaceFinish; static KIGFX::COLOR4D g_DefaultBoardBody; + static KIGFX::COLOR4D g_DefaultComments; + static KIGFX::COLOR4D g_DefaultECOs; public: EDA_3D_VIEWER_SETTINGS* m_Cfg; @@ -406,6 +418,10 @@ public: SFVEC4F m_SilkScreenColorBot; ///< in realistic mode: SilkScreen color ( bot ) SFVEC4F m_SilkScreenColorTop; ///< in realistic mode: SilkScreen color ( top ) SFVEC4F m_CopperColor; ///< in realistic mode: copper color + SFVEC4F m_UserDrawingsColor; + SFVEC4F m_UserCommentsColor; + SFVEC4F m_ECO1Color; + SFVEC4F m_ECO2Color; private: BOARD* m_board; diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index f87914eab6..96b76e1bfe 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro + * Copyright (C) 2023 CERN * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or @@ -162,14 +163,24 @@ void BOARD_ADAPTER::addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer, - PCB_LAYER_ID aLayerId ) + PCB_LAYER_ID aLayerId, + const std::bitset& aVisibilityFlags ) { KIGFX::GAL_DISPLAY_OPTIONS empty_opts; for( PCB_FIELD* field : aFootprint->GetFields() ) { if( field->GetLayer() == aLayerId && field->IsVisible() ) + { + if( !aVisibilityFlags.test( LAYER_FP_TEXT ) ) + continue; + else if( field->IsReference() && !aVisibilityFlags.test( LAYER_FP_REFERENCES ) ) + continue; + else if( field->IsValue() && !aVisibilityFlags.test( LAYER_FP_VALUES ) ) + continue; + addText( field, aContainer, field ); + } } for( BOARD_ITEM* item : aFootprint->GraphicalItems() ) @@ -181,7 +192,16 @@ void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2 PCB_TEXT* text = static_cast( item ); if( text->GetLayer() == aLayerId && text->IsVisible() ) + { + if( !aVisibilityFlags.test( LAYER_FP_TEXT ) ) + continue; + else if( text->GetText() == wxT( "${REFERENCE}" ) && !aVisibilityFlags.test( LAYER_FP_REFERENCES ) ) + continue; + else if( text->GetText() == wxT( "${VALUE}" ) && !aVisibilityFlags.test( LAYER_FP_VALUES ) ) + continue; + addText( text, aContainer, text ); + } break; } diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 9a5b813e70..0b3d433ce1 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -138,6 +139,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) PCB_LAYER_ID cu_seq[MAX_CU_LAYERS]; LSET cu_set = LSET::AllCuMask( m_copperLayersCount ); + std::bitset visibilityFlags = GetVisibleLayers(); + m_trackCount = 0; m_averageTrackWidth = 0; m_viaCount = 0; @@ -157,7 +160,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) for( PCB_TRACK* track : m_board->Tracks() ) { - if( !Is3dLayerEnabled( track->GetLayer() ) ) // Skip non enabled layers + if( !Is3dLayerEnabled( track->GetLayer(), visibilityFlags ) ) // Skip non enabled layers continue; // Note: a PCB_TRACK holds normal segment tracks and also vias circles (that have also @@ -196,7 +199,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { const PCB_LAYER_ID layer = *cu; - if( !Is3dLayerEnabled( layer ) ) // Skip non enabled layers + if( !Is3dLayerEnabled( layer, visibilityFlags ) ) // Skip non enabled layers continue; layer_ids.push_back( layer ); @@ -530,7 +533,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) addPads( footprint, layerContainer, layer, renderPlatedPadsAsPlated, false ); // Micro-wave footprints may have items on copper layers - addFootprintShapes( footprint, layerContainer, layer ); + addFootprintShapes( footprint, layerContainer, layer, visibilityFlags ); } } @@ -889,14 +892,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) Margin }; - // User layers are not drawn here, only technical layers for( LSEQ seq = LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) ); seq; ++seq ) { const PCB_LAYER_ID layer = *seq; - if( !Is3dLayerEnabled( layer ) ) + if( !Is3dLayerEnabled( layer, visibilityFlags ) ) continue; if( aStatusReporter ) @@ -1027,7 +1029,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) addPads( footprint, layerContainer, layer, false, false ); } - addFootprintShapes( footprint, layerContainer, layer ); + addFootprintShapes( footprint, layerContainer, layer, visibilityFlags ); } diff --git a/3d-viewer/3d_rendering/opengl/create_scene.cpp b/3d-viewer/3d_rendering/opengl/create_scene.cpp index feced0f1f6..cae7eac280 100644 --- a/3d-viewer/3d_rendering/opengl/create_scene.cpp +++ b/3d-viewer/3d_rendering/opengl/create_scene.cpp @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -565,13 +566,14 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo if( aStatusReporter ) aStatusReporter->Report( _( "Load OpenGL: layers" ) ); - const MAP_POLY& map_poly = m_boardAdapter.GetPolyMap(); + std::bitset visibilityFlags = m_boardAdapter.GetVisibleLayers(); + const MAP_POLY& map_poly = m_boardAdapter.GetPolyMap(); for( const std::pair& ii : m_boardAdapter.GetLayerMap() ) { const PCB_LAYER_ID layer_id = ii.first; - if( !m_boardAdapter.Is3dLayerEnabled( layer_id ) ) + if( !m_boardAdapter.Is3dLayerEnabled( layer_id, visibilityFlags ) ) continue; if( aStatusReporter ) diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp index 90b9c0baf3..cce8f7bc3a 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2020 Mario Luzeiro - * Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -428,11 +429,22 @@ SFVEC4F RENDER_3D_OPENGL::getLayerColor( PCB_LAYER_ID aLayerID ) break; case Dwgs_User: + layerColor = m_boardAdapter.m_UserDrawingsColor; + break; case Cmts_User: + layerColor = m_boardAdapter.m_UserCommentsColor; + break; case Eco1_User: + layerColor = m_boardAdapter.m_ECO1Color; + break; case Eco2_User: + layerColor = m_boardAdapter.m_ECO2Color; + break; + case Edge_Cuts: case Margin: + layerColor = m_boardAdapter.m_UserDrawingsColor; + break; break; case B_CrtYd: @@ -878,7 +890,8 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter, renderBoardBody( skipRenderHoles ); // Display transparent mask layers - if( m_boardAdapter.m_Cfg->m_Render.show_soldermask ) + if( m_boardAdapter.m_Cfg->m_Render.show_soldermask_top + || m_boardAdapter.m_Cfg->m_Render.show_soldermask_bottom ) { // add a depth buffer offset, it will help to hide some artifacts // on silkscreen where the SolderMask is removed @@ -887,19 +900,31 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter, if( m_camera.GetPos().z > 0 ) { - renderSolderMaskLayer( B_Mask, m_boardAdapter.GetLayerTopZPos( B_Mask ), - drawMiddleSegments, skipRenderHoles ); + if( m_boardAdapter.m_Cfg->m_Render.show_soldermask_bottom ) + { + renderSolderMaskLayer( B_Mask, m_boardAdapter.GetLayerTopZPos( B_Mask ), + drawMiddleSegments, skipRenderHoles ); + } - renderSolderMaskLayer( F_Mask, m_boardAdapter.GetLayerBottomZPos( F_Mask ), - drawMiddleSegments, skipRenderHoles ); + if( m_boardAdapter.m_Cfg->m_Render.show_soldermask_top ) + { + renderSolderMaskLayer( F_Mask, m_boardAdapter.GetLayerBottomZPos( F_Mask ), + drawMiddleSegments, skipRenderHoles ); + } } else { - renderSolderMaskLayer( F_Mask, m_boardAdapter.GetLayerBottomZPos( F_Mask ), - drawMiddleSegments, skipRenderHoles ); + if( m_boardAdapter.m_Cfg->m_Render.show_soldermask_top ) + { + renderSolderMaskLayer( F_Mask, m_boardAdapter.GetLayerBottomZPos( F_Mask ), + drawMiddleSegments, skipRenderHoles ); + } - renderSolderMaskLayer( B_Mask, m_boardAdapter.GetLayerTopZPos( B_Mask ), - drawMiddleSegments, skipRenderHoles ); + if( m_boardAdapter.m_Cfg->m_Render.show_soldermask_bottom ) + { + renderSolderMaskLayer( B_Mask, m_boardAdapter.GetLayerTopZPos( B_Mask ), + drawMiddleSegments, skipRenderHoles ); + } } glDisable( GL_POLYGON_OFFSET_FILL ); diff --git a/3d-viewer/3d_rendering/raytracing/create_scene.cpp b/3d-viewer/3d_rendering/raytracing/create_scene.cpp index f2b0d852fe..4558a01406 100644 --- a/3d-viewer/3d_rendering/raytracing/create_scene.cpp +++ b/3d-viewer/3d_rendering/raytracing/create_scene.cpp @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2022 Mario Luzeiro - * Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -615,11 +616,24 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe break; case Dwgs_User: + layerColor = m_boardAdapter.m_UserDrawingsColor; + break; + case Cmts_User: + layerColor = m_boardAdapter.m_UserCommentsColor; + break; + case Eco1_User: + layerColor = m_boardAdapter.m_ECO1Color; + break; + case Eco2_User: + layerColor = m_boardAdapter.m_ECO2Color; + break; + case Edge_Cuts: case Margin: + layerColor = m_boardAdapter.m_UserDrawingsColor; break; case B_CrtYd: @@ -674,8 +688,9 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe // Solder mask layers are "negative" layers so the elements that we have in the container // should remove the board outline. We will check for all objects in the outline if it // intersects any object in the layer container and also any hole. - if( m_boardAdapter.m_Cfg->m_Render.show_soldermask - && !m_outlineBoard2dObjects->GetList().empty() ) + if( ( m_boardAdapter.m_Cfg->m_Render.show_soldermask_top + || m_boardAdapter.m_Cfg->m_Render.show_soldermask_bottom ) + && !m_outlineBoard2dObjects->GetList().empty() ) { const MATERIAL* materialLayer = &m_materials.m_SolderMask; @@ -689,8 +704,23 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe continue; // Only get the Solder mask layers (and only if the board has them) - if( !( layer_id == B_Mask || layer_id == F_Mask ) ) + switch( layer_id ) + { + case F_Mask: + if( !m_boardAdapter.m_Cfg->m_Render.show_soldermask_top ) + continue; + + break; + + case B_Mask: + if( !m_boardAdapter.m_Cfg->m_Render.show_soldermask_bottom ) + continue; + + break; + + default: continue; + } SFVEC3F layerColor; diff --git a/3d-viewer/3d_viewer/3d_menubar.cpp b/3d-viewer/3d_viewer/3d_menubar.cpp index 4886c5be61..1b334492a2 100644 --- a/3d-viewer/3d_viewer/3d_menubar.cpp +++ b/3d-viewer/3d_viewer/3d_menubar.cpp @@ -4,7 +4,8 @@ * Copyright (C) 2016 Mario Luzeiro * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2013 Wayne Stambaugh - * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -99,6 +100,9 @@ void EDA_3D_VIEWER_FRAME::CreateMenuBar() viewMenu->Add( EDA_3D_ACTIONS::moveUp ); viewMenu->Add( EDA_3D_ACTIONS::moveDown ); + viewMenu->AppendSeparator(); + viewMenu->Add( EDA_3D_ACTIONS::showLayersManager, ACTION_MENU::CHECK ); + //-- Preferences menu ----------------------------------------------- // @@ -123,8 +127,8 @@ void EDA_3D_VIEWER_FRAME::CreateMenuBar() prefsMenu->AppendSeparator(); - prefsMenu->Add( EDA_3D_ACTIONS::showAxis, ACTION_MENU::CHECK ); - prefsMenu->Add( EDA_3D_ACTIONS::showBBoxes, ACTION_MENU::CHECK ); + prefsMenu->Add( EDA_3D_ACTIONS::showAxis, ACTION_MENU::CHECK ); + prefsMenu->Add( EDA_3D_ACTIONS::showBBoxes, ACTION_MENU::CHECK ); // Grid submenu ACTION_MENU* gridSubmenu = new ACTION_MENU( false, tool ); diff --git a/3d-viewer/3d_viewer/3d_toolbar.cpp b/3d-viewer/3d_viewer/3d_toolbar.cpp index 90a7783b50..85960b51a4 100644 --- a/3d-viewer/3d_viewer/3d_toolbar.cpp +++ b/3d-viewer/3d_viewer/3d_toolbar.cpp @@ -4,7 +4,8 @@ * Copyright (C) 2016 Mario Luzeiro * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2013 Wayne Stambaugh - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -52,32 +53,6 @@ void EDA_3D_VIEWER_FRAME::ReCreateMainToolbar() m_mainToolBar->SetAuiManager( &m_auimgr ); } - // Show the hotkey to open the windows list selector: - wxString keyName = KeyNameFromKeyCode( VIEWPORT_SWITCH_KEY ); - - m_viewportsLabel = new wxStaticText( m_mainToolBar, wxID_ANY, - wxString::Format( _( "Viewports (%s+Tab):" ), keyName ) ); - m_viewportsLabel->Wrap( -1 ); - - m_cbViewports = new wxChoice( m_mainToolBar, wxID_ANY ); - - for( std::pair& pair : m_viewports ) - m_cbViewports->Append( pair.first, static_cast( &pair.second ) ); - - m_cbViewports->Append( wxT( "---" ) ); - m_cbViewports->Append( _( "Save viewport..." ) ); - m_cbViewports->Append( _( "Delete viewport..." ) ); - - m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore view orientation and zoom.\n" - "Use %s+Tab to activate selector.\n" - "Successive Tabs while holding %s down will " - "cycle through viewports in the popup." ), - keyName, keyName ) ); - - m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); - - m_lastSelectedViewport = nullptr; - // Set up toolbar m_mainToolBar->AddTool( ID_RELOAD3D_BOARD, wxEmptyString, KiScaledBitmap( BITMAPS::import3d, this ), _( "Reload board" ) ); @@ -123,15 +98,7 @@ void EDA_3D_VIEWER_FRAME::ReCreateMainToolbar() m_mainToolBar->Add( EDA_3D_ACTIONS::toggleOrtho, ACTION_TOOLBAR::TOGGLE ); m_mainToolBar->AddScaledSeparator( this ); - m_mainToolBar->Add( EDA_3D_ACTIONS::showTHT, ACTION_TOOLBAR::TOGGLE ); - m_mainToolBar->Add( EDA_3D_ACTIONS::showSMD, ACTION_TOOLBAR::TOGGLE ); - m_mainToolBar->Add( EDA_3D_ACTIONS::showVirtual, ACTION_TOOLBAR::TOGGLE ); - m_mainToolBar->Add( EDA_3D_ACTIONS::showNotInPosFile, ACTION_TOOLBAR::TOGGLE ); - m_mainToolBar->Add( EDA_3D_ACTIONS::showDNP, ACTION_TOOLBAR::TOGGLE ); - - m_mainToolBar->AddScaledSeparator( this ); - m_mainToolBar->AddControl( m_viewportsLabel ); - m_mainToolBar->AddControl( m_cbViewports ); + m_mainToolBar->Add( EDA_3D_ACTIONS::showLayersManager, ACTION_TOOLBAR::TOGGLE ); m_mainToolBar->KiRealize(); } diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp index d01617f63b..52bffd979e 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp +++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro + * Copyright (C) 2023 CERN * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or @@ -28,11 +29,9 @@ #include #include #include -#include #include #include "eda_3d_viewer_frame.h" -#include "eda_list_dialog.h" -#include "wx/generic/textdlgg.h" +#include "dialogs/appearance_controls_3D.h" #include #include #include <3d_viewer_id.h> @@ -55,6 +54,7 @@ #include #include #include +#include #include #include <3d_navlib/nl_3d_viewer_plugin.h> @@ -89,10 +89,12 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent const wxString& aTitle, long style ) : KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle, wxDefaultPosition, wxDefaultSize, style, QUALIFIED_VIEWER3D_FRAMENAME( aParent ), unityScale ), - m_mainToolBar( nullptr ), m_canvas( nullptr ), m_currentCamera( m_trackBallCamera ), - m_viewportsLabel( nullptr ), - m_cbViewports( nullptr ), - m_trackBallCamera( 2 * RANGE_SCALE_3D ), m_spaceMouse( nullptr ) + m_mainToolBar( nullptr ), + m_canvas( nullptr ), + m_currentCamera( m_trackBallCamera ), + m_trackBallCamera( 2 * RANGE_SCALE_3D ), + m_spaceMouse( nullptr ), + m_showAppearanceManager( true ) { wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME %s" ), aTitle ); @@ -114,13 +116,15 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent EDA_3D_VIEWER_SETTINGS* cfg = mgr.GetAppSettings(); ANTIALIASING_MODE aaMode = static_cast( cfg->m_Render.opengl_AA_mode ); - m_canvas = new EDA_3D_CANVAS( this, OGL_ATT_LIST::GetAttributesList( aaMode ), - m_boardAdapter, m_currentCamera, Prj().Get3DCacheManager() ); + m_canvas = new EDA_3D_CANVAS( this, OGL_ATT_LIST::GetAttributesList( aaMode ), m_boardAdapter, + m_currentCamera, Prj().Get3DCacheManager() ); + + m_appearancePanel = new APPEARANCE_CONTROLS_3D( this, GetCanvas() ); LoadSettings( cfg ); loadCommonSettings(); - SetUserViewports( Prj().GetProjectFile().m_Viewports3D ); + m_appearancePanel->SetUserViewports( Prj().GetProjectFile().m_Viewports3D ); // Create the manager m_toolManager = new TOOL_MANAGER; @@ -150,9 +154,23 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent m_auimgr.SetManagedWindow( this ); - m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( wxS( "MainToolbar" ) ).Top().Layer( 6 ) ); - m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ).Top().Layer( 1 ) ); - m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) ).Center() ); + m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( wxS( "MainToolbar" ) ) + .Top().Layer( 6 ) ); + m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ) + .Top().Layer( 1 ) ); + m_auimgr.AddPane( m_appearancePanel, EDA_PANE().Name( "LayersManager" ) + .Right().Layer( 3 ) + .Caption( _( "Appearance" ) ).PaneBorder( false ) + .MinSize( 180, -1 ).BestSize( 190, -1 ) ); + m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( wxS( "DrawFrame" ) ) + .Center() ); + + wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" ); + + if( cfg->m_AuiPanels.right_panel_width > 0 ) + SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 ); + + layersManager.Show( m_showAppearanceManager ); // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before // hiding it. @@ -178,13 +196,6 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent // in order to receive mouse events. Otherwise, the user has to click somewhere on // the canvas before it will respond to mouse wheel events. m_canvas->SetFocus(); - - m_cbViewports->Connect( wxEVT_COMMAND_CHOICE_SELECTED, - wxCommandEventHandler( EDA_3D_VIEWER_FRAME::onViewportChanged ), - nullptr, this ); - m_cbViewports->Connect( wxEVT_UPDATE_UI, - wxUpdateUIEventHandler( EDA_3D_VIEWER_FRAME::onUpdateViewportsCb ), - nullptr, this ); } @@ -192,14 +203,7 @@ EDA_3D_VIEWER_FRAME::~EDA_3D_VIEWER_FRAME() { delete m_spaceMouse; - Prj().GetProjectFile().m_Viewports3D = GetUserViewports(); - - m_cbViewports->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, - wxCommandEventHandler( EDA_3D_VIEWER_FRAME::onViewportChanged ), - nullptr, this ); - m_cbViewports->Disconnect( wxEVT_UPDATE_UI, - wxUpdateUIEventHandler( EDA_3D_VIEWER_FRAME::onUpdateViewportsCb ), - nullptr, this ); + Prj().GetProjectFile().m_Viewports3D = m_appearancePanel->GetUserViewports(); m_canvas->SetEventDispatcher( nullptr ); @@ -288,6 +292,7 @@ void EDA_3D_VIEWER_FRAME::setupUIConditions() bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent ) { + static bool s_presetSwitcherShown = false; static bool s_viewportSwitcherShown = false; // wxWidgets generates no key events for the tab key when the ctrl key is held down. One @@ -301,13 +306,49 @@ bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent ) && static_cast( aEvent ).GetKeyCode() == WXK_TAB ) #endif { - if( !s_viewportSwitcherShown && wxGetKeyState( VIEWPORT_SWITCH_KEY ) ) + if( !s_presetSwitcherShown && wxGetKeyState( PRESET_SWITCH_KEY ) ) + { + if( m_appearancePanel && this->IsActive() ) + { + wxArrayString mru = m_appearancePanel->GetLayerPresetsMRU(); + + if( mru.size() > 0 ) + { + for( wxString& str : mru ) + { + if( str == FOLLOW_PCB ) + str = _( "Follow PCB Editor" ); + else if( str == FOLLOW_PLOT_SETTINGS ) + str = _( "Follow PCB Plot Settings" ); + } + + EDA_VIEW_SWITCHER switcher( this, mru, PRESET_SWITCH_KEY ); + + s_presetSwitcherShown = true; + switcher.ShowModal(); + s_presetSwitcherShown = false; + + int idx = switcher.GetSelection(); + + if( idx >= 0 && idx < (int) mru.size() ) + { + wxString internalName = m_appearancePanel->GetLayerPresetsMRU()[idx]; + m_appearancePanel->ApplyLayerPreset( internalName ); + } + + return true; + } + } + } + else if( !s_viewportSwitcherShown && wxGetKeyState( VIEWPORT_SWITCH_KEY ) ) { if( this->IsActive() ) { - if( m_viewportMRU.size() > 0 ) + const wxArrayString& viewportMRU = m_appearancePanel->GetViewportsMRU(); + + if( viewportMRU.size() > 0 ) { - EDA_VIEW_SWITCHER switcher( this, m_viewportMRU, VIEWPORT_SWITCH_KEY ); + EDA_VIEW_SWITCHER switcher( this, viewportMRU, VIEWPORT_SWITCH_KEY ); s_viewportSwitcherShown = true; switcher.ShowModal(); @@ -315,8 +356,8 @@ bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent ) int idx = switcher.GetSelection(); - if( idx >= 0 && idx < (int) m_viewportMRU.size() ) - applyViewport( m_viewportMRU[idx] ); + if( idx >= 0 && idx < (int) viewportMRU.size() ) + m_appearancePanel->ApplyViewport( viewportMRU[idx] ); return true; } @@ -339,6 +380,9 @@ void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent ) void EDA_3D_VIEWER_FRAME::ReloadRequest() { + if( m_appearancePanel ) + m_appearancePanel->UpdateLayerCtls(); + // This will schedule a request to load later if( m_canvas ) m_canvas->ReloadRequest( GetBoard(), Prj().Get3DCacheManager() ); @@ -347,7 +391,8 @@ void EDA_3D_VIEWER_FRAME::ReloadRequest() void EDA_3D_VIEWER_FRAME::NewDisplay( bool aForceImmediateRedraw ) { - ReloadRequest(); + if( m_canvas ) + m_canvas->ReloadRequest( GetBoard(), Prj().Get3DCacheManager() ); // After the ReloadRequest call, the refresh often takes a bit of time, // and it is made here only on request. @@ -385,6 +430,12 @@ void EDA_3D_VIEWER_FRAME::OnCloseWindow( wxCloseEvent &event ) { wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnCloseWindow" ) ); + // Do not show the layer manager during closing to avoid flicker + // on some platforms (Windows) that generate useless redraw of items in + // the Layer Manager + if( m_showAppearanceManager ) + m_auimgr.GetPane( wxS( "LayersManager" ) ).Show( false ); + if( m_canvas ) m_canvas->Close(); @@ -438,174 +489,6 @@ void EDA_3D_VIEWER_FRAME::Process_Special_Functions( wxCommandEvent &event ) } -std::vector EDA_3D_VIEWER_FRAME::GetUserViewports() const -{ - std::vector ret; - - for( const std::pair& pair : m_viewports ) - ret.emplace_back( pair.second ); - - return ret; -} - - -void EDA_3D_VIEWER_FRAME::SetUserViewports( std::vector& aViewportList ) -{ - m_viewports.clear(); - - for( const VIEWPORT3D& viewport : aViewportList ) - { - if( m_viewports.count( viewport.name ) ) - continue; - - m_viewports[viewport.name] = viewport; - - m_viewportMRU.Add( viewport.name ); - } -} - - -void EDA_3D_VIEWER_FRAME::applyViewport( const wxString& aViewportName ) -{ - int idx = m_cbViewports->FindString( aViewportName ); - - if( idx >= 0 && idx < m_cbViewports->GetCount() - 3 /* separator */ ) - { - m_cbViewports->SetSelection( idx ); - m_lastSelectedViewport = static_cast( m_cbViewports->GetClientData( idx ) ); - - m_currentCamera.SetViewMatrix( m_lastSelectedViewport->matrix ); - - if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL ) - m_canvas->Request_refresh(); - else - m_canvas->RenderRaytracingRequest(); - - if( !m_lastSelectedViewport->name.IsEmpty() ) - { - m_viewportMRU.Remove( m_lastSelectedViewport->name ); - m_viewportMRU.Insert( m_lastSelectedViewport->name, 0 ); - } - } - else - { - m_cbViewports->SetSelection( -1 ); // separator - m_lastSelectedViewport = nullptr; - } -} - - -void EDA_3D_VIEWER_FRAME::onViewportChanged( wxCommandEvent& aEvent ) -{ - int count = m_cbViewports->GetCount(); - int index = m_cbViewports->GetSelection(); - - if( index >= 0 && index < count - 3 /* separator */ ) - { - VIEWPORT3D* viewport = static_cast( m_cbViewports->GetClientData( index ) ); - - wxCHECK( viewport, /* void */ ); - - applyViewport( viewport->name ); - } - else if( index == count - 2 ) - { - // Save current state to new preset - wxString name; - - wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name ); - - if( dlg.ShowModal() != wxID_OK ) - { - if( m_lastSelectedViewport ) - m_cbViewports->SetStringSelection( m_lastSelectedViewport->name ); - else - m_cbViewports->SetSelection( -1 ); - - return; - } - - name = dlg.GetValue(); - bool exists = m_viewports.count( name ); - - if( !exists ) - { - m_viewports[name] = VIEWPORT3D( name, m_currentCamera.GetViewMatrix() ); - - index = m_cbViewports->Insert( name, index-1, static_cast( &m_viewports[name] ) ); - } - else - { - index = m_cbViewports->FindString( name ); - m_viewports[name].matrix = m_currentCamera.GetViewMatrix(); - m_viewportMRU.Remove( name ); - } - - m_cbViewports->SetSelection( index ); - m_viewportMRU.Insert( name, 0 ); - - return; - } - else if( index == count - 1 ) - { - // Delete an existing viewport - wxArrayString headers; - std::vector items; - - headers.Add( _( "Viewports" ) ); - - for( std::pair& pair : m_viewports ) - { - wxArrayString item; - item.Add( pair.first ); - items.emplace_back( item ); - } - - EDA_LIST_DIALOG dlg( this, _( "Delete Viewport" ), headers, items ); - dlg.SetListLabel( _( "Select viewport:" ) ); - - if( dlg.ShowModal() == wxID_OK ) - { - wxString viewportName = dlg.GetTextSelection(); - int idx = m_cbViewports->FindString( viewportName ); - - if( idx != wxNOT_FOUND ) - { - m_viewports.erase( viewportName ); - m_cbViewports->Delete( idx ); - m_viewportMRU.Remove( viewportName ); - } - } - - if( m_lastSelectedViewport ) - m_cbViewports->SetStringSelection( m_lastSelectedViewport->name ); - else - m_cbViewports->SetSelection( -1 ); - - return; - } - - passOnFocus(); -} - - -void EDA_3D_VIEWER_FRAME::onUpdateViewportsCb( wxUpdateUIEvent& aEvent ) -{ - int count = m_cbViewports->GetCount(); - int index = m_cbViewports->GetSelection(); - - if( index >= 0 && index < count - 3 ) - { - VIEWPORT3D* viewport = static_cast( m_cbViewports->GetClientData( index ) ); - - wxCHECK( viewport, /* void */ ); - - if( m_currentCamera.GetViewMatrix() != viewport->matrix ) - m_cbViewports->SetSelection( -1 ); - } -} - - void EDA_3D_VIEWER_FRAME::onRenderEngineSelection( wxCommandEvent &event ) { RENDER_ENGINE& engine = m_boardAdapter.m_Cfg->m_Render.engine; @@ -666,13 +549,6 @@ void EDA_3D_VIEWER_FRAME::OnSetFocus( wxFocusEvent& aEvent ) } -void EDA_3D_VIEWER_FRAME::passOnFocus() -{ - if( m_canvas ) - m_canvas->SetFocus(); -} - - void EDA_3D_VIEWER_FRAME::LoadSettings( APP_SETTINGS_BASE *aCfg ) { EDA_BASE_FRAME::LoadSettings( aCfg ); @@ -685,6 +561,7 @@ void EDA_3D_VIEWER_FRAME::LoadSettings( APP_SETTINGS_BASE *aCfg ) if( cfg ) { m_boardAdapter.m_Cfg = cfg; + m_boardAdapter.SetBoard( GetBoard() ); // When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine // because the ray tracing is very time consuming, and can be seen as not working @@ -694,6 +571,35 @@ void EDA_3D_VIEWER_FRAME::LoadSettings( APP_SETTINGS_BASE *aCfg ) m_canvas->SetAnimationEnabled( cfg->m_Camera.animation_enabled ); m_canvas->SetMovingSpeedMultiplier( cfg->m_Camera.moving_speed_multiplier ); m_canvas->SetProjectionMode( cfg->m_Camera.projection_mode ); + + if( cfg->m_CurrentPreset == LEGACY_PRESET_FLAG ) + { + COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings(); + + if( colors->GetUseBoardStackupColors() ) + cfg->m_CurrentPreset = FOLLOW_PCB; + else + cfg->m_CurrentPreset = wxEmptyString; + + if( cfg->m_Render.realistic ) + { + // These settings are no longer dependent on realistic mode in 8.0 (you can use + // view presets to design whatever combinations you want), but we should at least + // default them to the same values as 7.0. + cfg->m_Render.show_comments = false; + cfg->m_Render.show_drawings = false; + cfg->m_Render.show_eco1 = false; + cfg->m_Render.show_eco2 = false; + cfg->m_Render.show_board_body = false; + } + } + + m_boardAdapter.InitSettings( nullptr, nullptr ); + + m_showAppearanceManager = cfg->m_AuiPanels.show_layer_manager; + + if( m_appearancePanel ) + m_appearancePanel->CommonSettingsChanged(); } } @@ -713,6 +619,9 @@ void EDA_3D_VIEWER_FRAME::SaveSettings( APP_SETTINGS_BASE *aCfg ) if( cfg ) { + cfg->m_AuiPanels.show_layer_manager = m_showAppearanceManager; + cfg->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x; + cfg->m_Camera.animation_enabled = m_canvas->GetAnimationEnabled(); cfg->m_Camera.moving_speed_multiplier = m_canvas->GetMovingSpeedMultiplier(); cfg->m_Camera.projection_mode = m_canvas->GetProjectionMode(); @@ -736,10 +645,42 @@ void EDA_3D_VIEWER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTex loadCommonSettings(); LoadSettings( Pgm().GetSettingsManager().GetAppSettings() ); + m_appearancePanel->CommonSettingsChanged(); + NewDisplay( true ); } +void EDA_3D_VIEWER_FRAME::ToggleAppearanceManager() +{ + SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager(); + EDA_3D_VIEWER_SETTINGS* cfg = mgr.GetAppSettings(); + wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" ); + + // show auxiliary Vertical layers and visibility manager toolbar + m_showAppearanceManager = !m_showAppearanceManager; + + layersManager.Show( m_showAppearanceManager ); + + if( m_showAppearanceManager ) + { + SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 ); + } + else + { + cfg->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x; + m_auimgr.Update(); + } +} + + +void EDA_3D_VIEWER_FRAME::OnDarkModeToggle() +{ + if( m_appearancePanel ) + m_appearancePanel->OnDarkModeToggle(); +} + + void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event ) { wxString fullFileName; diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_frame.h b/3d-viewer/3d_viewer/eda_3d_viewer_frame.h index af1efb0b52..0d61207bd0 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.h +++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.h @@ -4,7 +4,8 @@ * Copyright (C) 2015-2016 Mario Luzeiro * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -49,6 +50,8 @@ // Forward declarations class NL_3D_VIEWER_PLUGIN; +class APPEARANCE_CONTROLS_3D; + enum EDA_3D_VIEWER_STATUSBAR { @@ -106,9 +109,6 @@ public: EDA_3D_CANVAS* GetCanvas() { return m_canvas; } - std::vector GetUserViewports() const; - void SetUserViewports( std::vector& aViewportList ); - void SaveSettings( APP_SETTINGS_BASE* aCfg ) override; void LoadSettings( APP_SETTINGS_BASE* aCfg ) override; @@ -120,17 +120,17 @@ public: */ void CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged ) override; + APPEARANCE_CONTROLS_3D* GetAppearanceManager() { return m_appearancePanel; } + + void ToggleAppearanceManager(); + + void OnDarkModeToggle(); + protected: void setupUIConditions() override; void handleIconizeEvent( wxIconizeEvent& aEvent ) override; - /** - * switch to a given predefined 3D viewport - * @param aViewportName is the name of the viewport to switch on - */ - void applyViewport( const wxString& aViewportName ); - private: /// Called when user press the File->Exit void Exit3DFrame( wxCommandEvent& event ); @@ -143,12 +143,9 @@ private: void onRenderEngineSelection( wxCommandEvent& event ); void onDisableRayTracing( wxCommandEvent& aEvent ); - void onViewportChanged( wxCommandEvent& aEvent ); - void onUpdateViewportsCb( wxUpdateUIEvent& aEvent ); void OnActivate( wxActivateEvent& event ); void OnSetFocus( wxFocusEvent& event ); - void passOnFocus(); void CreateMenuBar(); void ReCreateMainToolbar(); @@ -177,21 +174,16 @@ private: wxFileName m_defaultSaveScreenshotFileName; ACTION_TOOLBAR* m_mainToolBar; - wxStaticText* m_viewportsLabel; - wxChoice* m_cbViewports; EDA_3D_CANVAS* m_canvas; BOARD_ADAPTER m_boardAdapter; CAMERA& m_currentCamera; TRACK_BALL m_trackBallCamera; bool m_disable_ray_tracing; + bool m_showAppearanceManager; NL_3D_VIEWER_PLUGIN* m_spaceMouse; - std::map m_viewports; - VIEWPORT3D* m_lastSelectedViewport; - wxArrayString m_viewportMRU; - /** * Trace mask used to enable or disable the trace output of this class. * The debug output can be turned on by setting the WXTRACE environment variable to diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_settings.cpp b/3d-viewer/3d_viewer/eda_3d_viewer_settings.cpp index fe8ac2b6d2..645ed3436b 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_settings.cpp +++ b/3d-viewer/3d_viewer/eda_3d_viewer_settings.cpp @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jon Evans - * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -22,21 +23,172 @@ #include #include #include +#include <3d_canvas/board_adapter.h> #include #include "eda_3d_viewer_settings.h" using KIGFX::COLOR4D; -///! Update the schema version whenever a migration is required -const int viewer3dSchemaVersion = 2; +using namespace std::placeholders; -EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() - : APP_SETTINGS_BASE( "3d_viewer", viewer3dSchemaVersion ), - m_Render(), - m_Camera() +LAYER_PRESET_3D::LAYER_PRESET_3D( const wxString& aName ) : + name( aName ) { + layers.set( LAYER_3D_BOARD ); + layers.set( LAYER_3D_COPPER_TOP ); + layers.set( LAYER_3D_COPPER_BOTTOM ); + layers.set( LAYER_3D_SILKSCREEN_TOP ); + layers.set( LAYER_3D_SILKSCREEN_BOTTOM ); + layers.set( LAYER_3D_SOLDERMASK_TOP ); + layers.set( LAYER_3D_SOLDERMASK_BOTTOM ); + layers.set( LAYER_3D_SOLDERPASTE ); + layers.set( LAYER_3D_ADHESIVE ); + + layers.set( LAYER_3D_TH_MODELS ); + layers.set( LAYER_3D_SMD_MODELS ); + + layers.set( LAYER_FP_REFERENCES ); + layers.set( LAYER_FP_TEXT ); + + layers.set( LAYER_GRID_AXES ); + + // Preload colors vector so we don't have to worry about exceptions using colors.at() + colors[ LAYER_3D_BACKGROUND_TOP ] = BOARD_ADAPTER::g_DefaultBackgroundTop; + colors[ LAYER_3D_BACKGROUND_BOTTOM ] = BOARD_ADAPTER::g_DefaultBackgroundBot; + colors[ LAYER_3D_BOARD ] = BOARD_ADAPTER::g_DefaultBoardBody; + colors[ LAYER_3D_COPPER_TOP ] = BOARD_ADAPTER::g_DefaultSurfaceFinish; + colors[ LAYER_3D_COPPER_BOTTOM ] = BOARD_ADAPTER::g_DefaultSurfaceFinish; + colors[ LAYER_3D_SILKSCREEN_TOP ] = BOARD_ADAPTER::g_DefaultSilkscreen; + colors[ LAYER_3D_SILKSCREEN_BOTTOM ] = BOARD_ADAPTER::g_DefaultSilkscreen; + colors[ LAYER_3D_SOLDERMASK_TOP ] = BOARD_ADAPTER::g_DefaultSolderMask; + colors[ LAYER_3D_SOLDERMASK_BOTTOM ] = BOARD_ADAPTER::g_DefaultSolderMask; + colors[ LAYER_3D_SOLDERPASTE ] = BOARD_ADAPTER::g_DefaultSolderPaste; + colors[ LAYER_3D_USER_DRAWINGS ] = BOARD_ADAPTER::g_DefaultComments; + colors[ LAYER_3D_USER_COMMENTS ] = BOARD_ADAPTER::g_DefaultComments; + colors[ LAYER_3D_USER_ECO1 ] = BOARD_ADAPTER::g_DefaultECOs; + colors[ LAYER_3D_USER_ECO2 ] = BOARD_ADAPTER::g_DefaultECOs; +} + + +PARAM_LAYER_PRESET_3D::PARAM_LAYER_PRESET_3D( const std::string& aPath, + std::vector* aPresetList ) : + PARAM_LAMBDA( aPath, + std::bind( &PARAM_LAYER_PRESET_3D::presetsToJson, this ), + std::bind( &PARAM_LAYER_PRESET_3D::jsonToPresets, this, _1 ), + {} ), + m_presets( aPresetList ) +{ + wxASSERT( aPresetList ); +} + + +nlohmann::json PARAM_LAYER_PRESET_3D::presetsToJson() +{ + nlohmann::json ret = nlohmann::json::array(); + + for( const LAYER_PRESET_3D& preset : *m_presets ) + { + nlohmann::json js = { + { "name", preset.name } + }; + + nlohmann::json layers = nlohmann::json::array(); + + for( int layer = 0; layer < LAYER_3D_END; ++layer ) + { + if( preset.layers.test( layer ) ) + layers.push_back( layer ); + } + + js["layers"] = layers; + + nlohmann::json colors = nlohmann::json::array(); + + for( const auto& [ layer, color ] : preset.colors ) + { + nlohmann::json layerColor = { + { "layer", layer }, + { "color", color.ToCSSString() } + }; + + colors.push_back( layerColor ); + } + + js["colors"] = colors; + + ret.push_back( js ); + } + + return ret; +} + + +void PARAM_LAYER_PRESET_3D::jsonToPresets( const nlohmann::json& aJson ) +{ + if( aJson.empty() || !aJson.is_array() ) + return; + + m_presets->clear(); + + for( const nlohmann::json& preset : aJson ) + { + if( preset.contains( "name" ) ) + { + LAYER_PRESET_3D p( preset.at( "name" ).get() ); + + if( preset.contains( "layers" ) && preset.at( "layers" ).is_array() ) + { + p.layers.reset(); + + for( const nlohmann::json& layer : preset.at( "layers" ) ) + { + if( layer.is_number_integer() ) + { + int layerNum = layer.get(); + + if( layerNum >= 0 && layerNum < LAYER_3D_END ) + p.layers.set( layerNum ); + } + } + } + + if( preset.contains( "colors" ) && preset.at( "colors" ).is_array() ) + { + for( const nlohmann::json& layerColor : preset.at( "colors" ) ) + { + if( layerColor.contains( "layer" ) && layerColor.contains( "color" ) + && layerColor.at( "layer" ).is_number_integer() ) + { + int layerNum = layerColor.at( "layer" ).get(); + COLOR4D color = layerColor.at( "color" ).get(); + p.colors[ layerNum ] = color; + } + } + } + + m_presets->emplace_back( p ); + } + } +} + + +///! Update the schema version whenever a migration is required +const int viewer3dSchemaVersion = 3; + + +EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() : + APP_SETTINGS_BASE( "3d_viewer", viewer3dSchemaVersion ), + m_Render(), + m_Camera() +{ + m_params.emplace_back( new PARAM( "aui.show_layer_manager", + &m_AuiPanels.show_layer_manager, true ) ); + + m_params.emplace_back( new PARAM( "aui.right_panel_width", + &m_AuiPanels.right_panel_width, -1 ) ); + m_params.emplace_back( new PARAM_ENUM( "render.engine", &m_Render.engine, RENDER_ENGINE::OPENGL, RENDER_ENGINE::OPENGL, @@ -172,8 +324,12 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() &m_Render.show_board_body, true ) ); m_params.emplace_back( new PARAM( "render.show_comments", &m_Render.show_comments, true ) ); - m_params.emplace_back( new PARAM( "render.show_eco", - &m_Render.show_eco, true ) ); + m_params.emplace_back( new PARAM( "render.show_drawings", + &m_Render.show_drawings, true ) ); + m_params.emplace_back( new PARAM( "render.show_eco1", + &m_Render.show_eco1, true ) ); + m_params.emplace_back( new PARAM( "render.show_eco2", + &m_Render.show_eco2, true ) ); m_params.emplace_back( new PARAM( "render.show_footprints_insert", &m_Render.show_footprints_insert, true ) ); m_params.emplace_back( new PARAM( "render.show_footprints_normal", @@ -184,14 +340,28 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() &m_Render.show_footprints_not_in_posfile, true ) ); m_params.emplace_back( new PARAM( "render.show_footprints_dnp", &m_Render.show_footprints_dnp, true ) ); - m_params.emplace_back( new PARAM( "render.show_silkscreen", - &m_Render.show_silkscreen, true ) ); - m_params.emplace_back( new PARAM( "render.show_soldermask", - &m_Render.show_soldermask, true ) ); + m_params.emplace_back( new PARAM( "render.show_silkscreen_top", + &m_Render.show_silkscreen_top, true ) ); + m_params.emplace_back( new PARAM( "render.show_silkscreen_bottom", + &m_Render.show_silkscreen_bottom, true ) ); + m_params.emplace_back( new PARAM( "render.show_soldermask_top", + &m_Render.show_soldermask_top, true ) ); + m_params.emplace_back( new PARAM( "render.show_soldermask_bottom", + &m_Render.show_soldermask_bottom, true ) ); m_params.emplace_back( new PARAM( "render.show_solderpaste", &m_Render.show_solderpaste, true ) ); + m_params.emplace_back( new PARAM( "render.show_copper_top", + &m_Render.show_copper_bottom, true ) ); + m_params.emplace_back( new PARAM( "render.show_copper_bottom", + &m_Render.show_copper_top, true ) ); m_params.emplace_back( new PARAM( "render.show_zones", &m_Render.show_zones, true ) ); + m_params.emplace_back( new PARAM( "render.show_fp_references", + &m_Render.show_fp_references, true ) ); + m_params.emplace_back( new PARAM( "render.show_fp_values", + &m_Render.show_fp_values, true ) ); + m_params.emplace_back( new PARAM( "render.show_fp_text", + &m_Render.show_fp_text, true ) ); m_params.emplace_back( new PARAM( "render.subtract_mask_from_silk", &m_Render.subtract_mask_from_silk, false ) ); m_params.emplace_back( new PARAM( "render.clip_silk_on_via_annulus", @@ -207,6 +377,11 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() m_params.emplace_back( new PARAM( "camera.projection_mode", &m_Camera.projection_mode, 1 ) ); + m_params.emplace_back( new PARAM_LAYER_PRESET_3D( "layer_presets", + &m_LayerPresets ) ); + m_params.emplace_back( new PARAM( "current_layer_preset", + &m_CurrentPreset, LEGACY_PRESET_FLAG ) ); + registerMigration( 0, 1, std::bind( &EDA_3D_VIEWER_SETTINGS::migrateSchema0to1, this ) ); registerMigration( 1, 2, @@ -215,6 +390,51 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() Set( "render.opengl_copper_thickness", false ); return true; } ); + + registerMigration( 2, 3, + [&]() -> bool + { + if( std::optional optval = Get( "render.show_copper" ) ) + { + Set( "render.show_copper_top", *optval ); + Set( "render.show_copper_bottom", *optval ); + } + + if( std::optional optval = Get( "render.show_silkscreen" ) ) + { + Set( "render.show_silkscreen_top", *optval ); + Set( "render.show_silkscreen_bottom", *optval ); + } + + if( std::optional optval = Get( "render.show_soldermask" ) ) + { + Set( "render.show_soldermask_top", *optval ); + Set( "render.show_soldermask_bottom", *optval ); + } + + if( std::optional optval = Get( "render.show_comments" ) ) + Set( "render.show_drawings", *optval ); + + if( std::optional optval = Get( "render.show_eco" ) ) + { + Set( "render.show_eco1", *optval ); + Set( "render.show_eco2", *optval ); + } + + return true; + } ); +} + + +LAYER_PRESET_3D* EDA_3D_VIEWER_SETTINGS::FindPreset( const wxString& aName ) +{ + for( LAYER_PRESET_3D& preset : m_LayerPresets ) + { + if( preset.name == aName ) + return &preset; + } + + return nullptr; } diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_settings.h b/3d-viewer/3d_viewer/eda_3d_viewer_settings.h index 7ffd98941d..38abb0bb2a 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_settings.h +++ b/3d-viewer/3d_viewer/eda_3d_viewer_settings.h @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jon Evans - * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,11 +27,55 @@ #include #include #include +#include #include "render_settings.h" +#define FOLLOW_PCB wxT( "follow_pcb_editor" ) +#define FOLLOW_PLOT_SETTINGS wxT( "follow_plot_settings" ) +#define LEGACY_PRESET_FLAG wxT( "legacy_preset_flag" ) + + +struct LAYER_PRESET_3D +{ + LAYER_PRESET_3D( const wxString& aName = wxEmptyString ); + + LAYER_PRESET_3D( const wxString& aName, const std::bitset& aLayers, + const std::map& aColors ) : + name( aName ), + layers( aLayers ), + colors( aColors ) + { + } + + wxString name; ///< A name for this layer set + std::bitset layers; + std::map colors; +}; + + +class PARAM_LAYER_PRESET_3D : public PARAM_LAMBDA +{ +public: + PARAM_LAYER_PRESET_3D( const std::string& aPath, std::vector* aPresetList ); + +private: + nlohmann::json presetsToJson(); + + void jsonToPresets( const nlohmann::json& aJson ); + + std::vector* m_presets; +}; + + class EDA_3D_VIEWER_SETTINGS : public APP_SETTINGS_BASE { public: + struct AUI_PANELS + { + int right_panel_width; + bool show_layer_manager; + }; + struct RENDER_SETTINGS { RENDER_ENGINE engine; @@ -79,16 +124,25 @@ public: bool show_axis; bool show_board_body; bool show_comments; - bool show_eco; + bool show_drawings; + bool show_eco1; + bool show_eco2; bool show_footprints_insert; bool show_footprints_normal; bool show_footprints_virtual; bool show_footprints_not_in_posfile; bool show_footprints_dnp; - bool show_silkscreen; - bool show_soldermask; + bool show_silkscreen_top; + bool show_silkscreen_bottom; + bool show_soldermask_top; + bool show_soldermask_bottom; bool show_solderpaste; + bool show_copper_top; + bool show_copper_bottom; bool show_zones; + bool show_fp_references; + bool show_fp_values; + bool show_fp_text; bool subtract_mask_from_silk; bool clip_silk_on_via_annulus; bool renderPlatedPadsAsPlated; @@ -106,11 +160,18 @@ public: virtual ~EDA_3D_VIEWER_SETTINGS() {} + LAYER_PRESET_3D* FindPreset( const wxString& aName ); + virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override; +public: + AUI_PANELS m_AuiPanels; RENDER_SETTINGS m_Render; CAMERA_SETTINGS m_Camera; + std::vector m_LayerPresets; + wxString m_CurrentPreset; + protected: virtual std::string getLegacyFrameName() const override { return "Viewer3DFrameName"; } diff --git a/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp b/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp index 72527c5d77..7adc2ee17b 100644 --- a/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp +++ b/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp @@ -2,7 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2017 Jon Evans - * Copyright (C) 2017-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -305,8 +306,8 @@ TOOL_ACTION EDA_3D_ACTIONS::showTHT( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.attributesTHT" ) .Scope( AS_ACTIVE ) .DefaultHotkey( 'T' ) - .MenuText( _( "Toggle Through Hole 3D models" ) ) - .Tooltip( _( "Toggle 3D models for 'Through hole' type components" ) ) + .MenuText( _( "Show Through Hole 3D Models" ) ) + .Tooltip( _( "Show 3D models for 'Through hole' type footprints" ) ) .Icon( BITMAPS::show_tht ) .Flags( AF_NONE ) ); @@ -314,8 +315,8 @@ TOOL_ACTION EDA_3D_ACTIONS::showSMD( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.attributesSMD" ) .Scope( AS_ACTIVE ) .DefaultHotkey( 'S' ) - .MenuText( _( "Toggle SMD 3D models" ) ) - .Tooltip( _( "Toggle 3D models for 'Surface mount' type components" ) ) + .MenuText( _( "Show SMD 3D Models" ) ) + .Tooltip( _( "Show 3D models for 'Surface mount' type footprints" ) ) .Icon( BITMAPS::show_smt ) .Flags( AF_NONE ) ); @@ -323,8 +324,8 @@ TOOL_ACTION EDA_3D_ACTIONS::showVirtual( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.attributesOther" ) .Scope( AS_ACTIVE ) .DefaultHotkey( 'V' ) - .MenuText( _( "Toggle unspecified 3D models" ) ) - .Tooltip( _( "Toggle 3D models for 'unspecified' type components" ) ) + .MenuText( _( "Show Unspecified 3D Models" ) ) + .Tooltip( _( "Show 3D models for 'unspecified' type footprints" ) ) .Icon( BITMAPS::show_other ) .Flags( AF_NONE ) ); @@ -332,8 +333,8 @@ TOOL_ACTION EDA_3D_ACTIONS::showNotInPosFile( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.attribute_not_in_posfile" ) .Scope( AS_ACTIVE ) .DefaultHotkey( 'P' ) - .MenuText( _( "Toggle 3D models not in pos file" ) ) - .Tooltip( _( "Toggle 3D models not in pos file" ) ) + .MenuText( _( "Show 3D Models not in POS File" ) ) + .Tooltip( _( "Show 3D models even if not found in .pos file" ) ) .Icon( BITMAPS::show_not_in_posfile ) .Flags( AF_NONE ) ); @@ -341,8 +342,8 @@ TOOL_ACTION EDA_3D_ACTIONS::showDNP( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.attribute_dnp" ) .Scope( AS_ACTIVE ) .DefaultHotkey( 'D' ) - .MenuText( _( "Toggle 3D models marked DNP" ) ) - .Tooltip( _( "Toggle 3D models for components marked 'Do Not Place'" ) ) + .MenuText( _( "Show 3D Models marked DNP" ) ) + .Tooltip( _( "Show 3D models even if marked 'Do Not Place'" ) ) .Icon( BITMAPS::show_dnp ) .Flags( AF_NONE ) ); @@ -350,22 +351,10 @@ TOOL_ACTION EDA_3D_ACTIONS::showBBoxes( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.showBoundingBoxes" ) .Scope( AS_GLOBAL ) .MenuText( _( "Show Model Bounding Boxes" ) ) - .Tooltip( _( "Show Model Bounding Boxes" ) ) + .Tooltip( _( "Show 3D model bounding boxes" ) ) .Icon( BITMAPS::ortho ) .Flags( AF_NONE ) ); -TOOL_ACTION EDA_3D_ACTIONS::toggleRealisticMode( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleRealisticMode" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle realistic mode" ) ) - .Tooltip( _( "Toggle realistic mode" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleBoardBody( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleBoardBody" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle board body display" ) ) - .Tooltip( _( "Toggle board body display" ) ) ); - TOOL_ACTION EDA_3D_ACTIONS::showAxis( TOOL_ACTION_ARGS() .Name( "3DViewer.Control.showAxis" ) .Scope( AS_GLOBAL ) @@ -374,45 +363,10 @@ TOOL_ACTION EDA_3D_ACTIONS::showAxis( TOOL_ACTION_ARGS() .Icon( BITMAPS::axis3d_front ) .Flags( AF_NONE ) ); -TOOL_ACTION EDA_3D_ACTIONS::toggleZones( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleZones" ) +TOOL_ACTION EDA_3D_ACTIONS::showLayersManager( TOOL_ACTION_ARGS() + .Name( "3DViewer.Control.showLayersManager" ) .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle zone display" ) ) - .Tooltip( _( "Toggle zone display" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleAdhesive( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleAdhesive" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle adhesive display" ) ) - .Tooltip( _( "Toggle display of adhesive layers" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleSilk( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleSilk" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle silkscreen display" ) ) - .Tooltip( _( "Toggle display of silkscreen layers" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleSolderMask( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleSolderMask" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle solder mask display" ) ) - .Tooltip( _( "Toggle display of solder mask layers" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleSolderPaste( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleSolderPaste" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle solder paste display" ) ) - .Tooltip( _( "Toggle display of solder paste layers" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleComments( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleComments" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle comments display" ) ) - .Tooltip( _( "Toggle display of comments and drawings layers" ) ) ); - -TOOL_ACTION EDA_3D_ACTIONS::toggleECO( TOOL_ACTION_ARGS() - .Name( "3DViewer.Control.toggleECO" ) - .Scope( AS_GLOBAL ) - .MenuText( _( "Toggle ECO display" ) ) - .Tooltip( _( "Toggle display of ECO layers" ) ) ); + .MenuText( _( "Show Appearance Manager" ) ) + .Tooltip( _( "Show/hide the appearance manager" ) ) + .Icon( BITMAPS::layers_manager ) ); diff --git a/3d-viewer/3d_viewer/tools/eda_3d_actions.h b/3d-viewer/3d_viewer/tools/eda_3d_actions.h index 80dc4511d2..8a6d767c7e 100644 --- a/3d-viewer/3d_viewer/tools/eda_3d_actions.h +++ b/3d-viewer/3d_viewer/tools/eda_3d_actions.h @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013-2016 CERN - * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013-2023 CERN + * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -81,16 +81,8 @@ public: static TOOL_ACTION showNotInPosFile; static TOOL_ACTION showDNP; static TOOL_ACTION showBBoxes; - static TOOL_ACTION toggleRealisticMode; - static TOOL_ACTION toggleBoardBody; static TOOL_ACTION showAxis; - static TOOL_ACTION toggleZones; - static TOOL_ACTION toggleAdhesive; - static TOOL_ACTION toggleSilk; - static TOOL_ACTION toggleSolderMask; - static TOOL_ACTION toggleSolderPaste; - static TOOL_ACTION toggleComments; - static TOOL_ACTION toggleECO; + static TOOL_ACTION showLayersManager; }; #endif diff --git a/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp b/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp index 98ac81bfa5..53df8891e1 100644 --- a/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp +++ b/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp @@ -1,7 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,8 +29,9 @@ #include #include #include -#include "eda_3d_actions.h" -#include "dialogs/panel_preview_3d_model.h" +#include +#include +#include #include <3d_rendering/opengl/render_3d_opengl.h> @@ -79,8 +81,7 @@ void EDA_3D_CONTROLLER::Reset( RESET_REASON aReason ) { m_canvas = dynamic_cast( holder->GetToolCanvas() ); - EDA_3D_BOARD_HOLDER* holder3d = - dynamic_cast( holder ); + EDA_3D_BOARD_HOLDER* holder3d = dynamic_cast( holder ); wxASSERT( holder3d ); @@ -166,7 +167,7 @@ int EDA_3D_CONTROLLER::PanControl( const TOOL_EVENT& aEvent ) case ACTIONS::CURSOR_DOWN: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_DOWN ); break; case ACTIONS::CURSOR_LEFT: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_LEFT ); break; case ACTIONS::CURSOR_RIGHT: m_canvas->SetView3D( VIEW3D_TYPE::VIEW3D_PAN_RIGHT ); break; - default: wxFAIL; break; + default: wxFAIL; break; } return 0; @@ -186,7 +187,7 @@ int EDA_3D_CONTROLLER::RotateView( const TOOL_EVENT& aEvent ) case ROTATION_DIR::Y_CCW: m_camera->RotateY( -rotIncrement ); break; case ROTATION_DIR::Z_CW: m_camera->RotateZ( -rotIncrement ); break; case ROTATION_DIR::Z_CCW: m_camera->RotateZ( rotIncrement ); break; - default: wxFAIL; break; + default: wxFAIL; break; } if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL ) @@ -225,100 +226,44 @@ int EDA_3D_CONTROLLER::ToggleOrtho( const TOOL_EVENT& aEvent ) int EDA_3D_CONTROLLER::ToggleVisibility( const TOOL_EVENT& aEvent ) { - bool reload = false; + std::bitset visibilityFlags = m_boardAdapter->GetVisibleLayers(); + APPEARANCE_CONTROLS_3D* appearanceManager = nullptr; -#define FLIP( x ) x = !x + auto flipLayer = + [&]( int layer ) + { + appearanceManager->OnLayerVisibilityChanged( layer, !visibilityFlags.test( layer ) ); + }; - if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) ) + if( auto viewer = dynamic_cast( m_toolMgr->GetToolHolder() ) ) + appearanceManager = viewer->GetAppearanceManager(); + + if( appearanceManager ) { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_footprints_normal ); - reload = true; - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_footprints_insert ); - reload = true; - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_footprints_virtual ); - reload = true; - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNotInPosFile ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_footprints_not_in_posfile ); - reload = true; - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_footprints_dnp ); - reload = true; - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.opengl_show_model_bbox ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleRealisticMode ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.realistic ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleBoardBody ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_board_body ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::showAxis ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_axis ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleZones ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_zones ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleAdhesive ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_adhesive ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleSilk ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_silkscreen ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleSolderMask ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_soldermask ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleSolderPaste ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_solderpaste ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleComments ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_comments ); - } - else if( aEvent.IsAction( &EDA_3D_ACTIONS::toggleECO ) ) - { - FLIP( m_boardAdapter->m_Cfg->m_Render.show_eco ); + if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) ) + flipLayer( LAYER_3D_TH_MODELS ); + else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) ) + flipLayer( LAYER_3D_SMD_MODELS ); + else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) ) + flipLayer( LAYER_3D_VIRTUAL_MODELS ); + else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNotInPosFile ) ) + flipLayer( LAYER_3D_MODELS_NOT_IN_POS ); + else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) ) + flipLayer( LAYER_3D_MODELS_MARKED_DNP ); + else if( aEvent.IsAction( &EDA_3D_ACTIONS::showAxis ) ) + flipLayer( LAYER_3D_AXES ); + else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) ) + flipLayer( LAYER_3D_BOUNDING_BOXES ); } - if( reload ) - { - if( m_boardAdapter->m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL ) - { - auto* renderer = static_cast( m_canvas->GetCurrentRender() ); - renderer->Load3dModelsIfNeeded(); - m_canvas->Request_refresh(); - } - else - { - m_canvas->RenderRaytracingRequest(); - } - } - else - { - if( auto viewer = dynamic_cast( m_toolMgr->GetToolHolder() ) ) - viewer->NewDisplay( true ); - else - m_canvas->Request_refresh(); - } + return 0; +} + + +int EDA_3D_CONTROLLER::ToggleLayersManager( const TOOL_EVENT& aEvent ) +{ + if( auto* viewer = dynamic_cast( m_toolMgr->GetToolHolder() ) ) + viewer->ToggleAppearanceManager(); return 0; } @@ -444,17 +389,7 @@ void EDA_3D_CONTROLLER::setTransitions() Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showNotInPosFile.MakeEvent() ); Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showDNP.MakeEvent() ); Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showVirtual.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showBBoxes.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleRealisticMode.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleBoardBody.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::showAxis.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleZones.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleAdhesive.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleSilk.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleSolderMask.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleSolderPaste.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleComments.MakeEvent() ); - Go( &EDA_3D_CONTROLLER::ToggleVisibility, EDA_3D_ACTIONS::toggleECO.MakeEvent() ); + Go( &EDA_3D_CONTROLLER::ToggleLayersManager,EDA_3D_ACTIONS::showLayersManager.MakeEvent() ); } diff --git a/3d-viewer/3d_viewer/tools/eda_3d_controller.h b/3d-viewer/3d_viewer/tools/eda_3d_controller.h index b6b24dae1a..35d0290480 100644 --- a/3d-viewer/3d_viewer/tools/eda_3d_controller.h +++ b/3d-viewer/3d_viewer/tools/eda_3d_controller.h @@ -1,7 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023 CERN + * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -95,6 +96,7 @@ public: int ToggleOrtho( const TOOL_EVENT& aEvent ); int ToggleVisibility( const TOOL_EVENT& aEvent ); + int ToggleLayersManager( const TOOL_EVENT& aEvent ); private: ///< Sets up handlers for various events. diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index 54b48891d4..2b42123a8e 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -16,7 +16,6 @@ include_directories( ) # directories -set( DIR_DLG dialogs ) set( DIR_RAY 3d_rendering/raytracing ) set( DIR_RAY_ACC ${DIR_RAY}/accelerators ) set( DIR_RAY_2D ${DIR_RAY}/shapes2D ) @@ -28,11 +27,6 @@ set(3D-VIEWER_SRCS ${DIR_3D_PLUGINS}/3d/pluginldr3D.cpp 3d_cache/3d_cache.cpp 3d_cache/3d_plugin_manager.cpp - ${DIR_DLG}/3d_cache_dialogs.cpp - ${DIR_DLG}/dialog_select_3d_model_base.cpp - ${DIR_DLG}/dialog_select_3d_model.cpp - ${DIR_DLG}/panel_preview_3d_model_base.cpp - ${DIR_DLG}/panel_preview_3d_model.cpp 3d_canvas/board_adapter.cpp 3d_canvas/create_layer_items.cpp 3d_canvas/create_3Dgraphic_brd_items.cpp @@ -88,14 +82,6 @@ set(3D-VIEWER_SRCS 3d_rendering/trackball.cpp 3d_viewer/3d_menubar.cpp 3d_viewer/3d_toolbar.cpp - dialogs/panel_3D_colors.cpp - dialogs/panel_3D_colors_base.cpp - dialogs/panel_3D_display_options.cpp - dialogs/panel_3D_display_options_base.cpp - dialogs/panel_3D_opengl_options.cpp - dialogs/panel_3D_opengl_options_base.cpp - dialogs/panel_3D_raytracing_options.cpp - dialogs/panel_3D_raytracing_options_base.cpp 3d_viewer/tools/eda_3d_actions.cpp 3d_viewer/tools/eda_3d_conditions.cpp 3d_viewer/tools/eda_3d_controller.cpp @@ -105,6 +91,21 @@ set(3D-VIEWER_SRCS common_ogl/ogl_utils.cpp 3d_fastmath.cpp 3d_math.cpp + dialogs/3d_cache_dialogs.cpp + dialogs/appearance_controls_3D.cpp + dialogs/appearance_controls_3D_base.cpp + dialogs/dialog_select_3d_model_base.cpp + dialogs/dialog_select_3d_model.cpp + dialogs/panel_preview_3d_model_base.cpp + dialogs/panel_preview_3d_model.cpp + dialogs/panel_3D_colors.cpp + dialogs/panel_3D_colors_base.cpp + dialogs/panel_3D_display_options.cpp + dialogs/panel_3D_display_options_base.cpp + dialogs/panel_3D_opengl_options.cpp + dialogs/panel_3D_opengl_options_base.cpp + dialogs/panel_3D_raytracing_options.cpp + dialogs/panel_3D_raytracing_options_base.cpp ) add_library(3d-viewer STATIC ${3D-VIEWER_SRCS}) diff --git a/3d-viewer/dialogs/appearance_controls_3D.cpp b/3d-viewer/dialogs/appearance_controls_3D.cpp new file mode 100644 index 0000000000..08088b4a77 --- /dev/null +++ b/3d-viewer/dialogs/appearance_controls_3D.cpp @@ -0,0 +1,864 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 CERN + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RR APPEARANCE_CONTROLS_3D::APPEARANCE_SETTING_3D // Render Row abbreviation to reduce source width + +/// Template for object appearance settings +const APPEARANCE_CONTROLS_3D::APPEARANCE_SETTING_3D APPEARANCE_CONTROLS_3D::s_layerSettings[] = { + + // text id tooltip + RR( _HKI( "Board Body" ), LAYER_3D_BOARD, _HKI( "Show board body" ) ), + RR( _HKI( "F.Cu" ), LAYER_3D_COPPER_TOP, _HKI( "Show front copper / surface finish color" ) ), + RR( _HKI( "B.Cu" ), LAYER_3D_COPPER_BOTTOM, _HKI( "Show back copper / surface finish color" ) ), + RR( _HKI( "Adhesive" ), LAYER_3D_ADHESIVE, _HKI( "Show adhesive" ) ), + RR( _HKI( "Solder Paste" ), LAYER_3D_SOLDERPASTE, _HKI( "Show solder paste" ) ), + RR( _HKI( "F.Silkscreen" ), LAYER_3D_SILKSCREEN_TOP, _HKI( "Show front silkscreen" ) ), + RR( _HKI( "B.Silkscreen" ), LAYER_3D_SILKSCREEN_BOTTOM, _HKI( "Show back silkscreen" ) ), + RR( _HKI( "F.Mask" ), LAYER_3D_SOLDERMASK_TOP, _HKI( "Show front solder mask" ) ), + RR( _HKI( "B.Mask" ), LAYER_3D_SOLDERMASK_BOTTOM, _HKI( "Show back solder mask" ) ), + RR( _HKI( "User.Drawings" ), LAYER_3D_USER_DRAWINGS, _HKI( "Show user drawings layer" ) ), + RR( _HKI( "User.Comments" ), LAYER_3D_USER_COMMENTS, _HKI( "Show user comments layer" ) ), + RR( _HKI( "User.Eco1" ), LAYER_3D_USER_ECO1, _HKI( "Show user ECO1 layer" ) ), + RR( _HKI( "User.Eco2" ), LAYER_3D_USER_ECO2, _HKI( "Show user ECO2 layer" ) ), + RR(), + RR( _HKI( "Through-hole Models" ), LAYER_3D_TH_MODELS, _HKI( "Show models for 'Through hole' footprints" ) ), + RR( _HKI( "SMD Models" ), LAYER_3D_SMD_MODELS, _HKI( "Show models for 'SMD' footprints" ) ), + RR( _HKI( "Virtual Models" ), LAYER_3D_VIRTUAL_MODELS, _HKI( "Show models for 'Unspecified' footprints" ) ), + RR( _HKI( "Models not in POS File" ), LAYER_3D_MODELS_NOT_IN_POS, _HKI( "Show models even if not in POS file" ) ), + RR( _HKI( "Models marked DNP" ), LAYER_3D_MODELS_MARKED_DNP, _HKI( "Show models even if marked as DNP" ) ), + RR( _HKI( "Model Bounding Boxes" ), LAYER_3D_BOUNDING_BOXES, _HKI( "Show model bounding boxes in realtime renderer" ) ), + RR(), + RR( _HKI( "Values" ), LAYER_FP_VALUES, _HKI( "Show footprint values" ) ), + RR( _HKI( "References" ), LAYER_FP_REFERENCES, _HKI( "Show footprint references" ) ), + RR( _HKI( "Footprint Text" ), LAYER_FP_TEXT, _HKI( "Show all footprint text" ) ), + RR(), + RR( _HKI( "3D Axis" ), LAYER_3D_AXES, _HKI( "Show 3D axes indicator" ) ), + RR( _HKI( "Background Start" ), LAYER_3D_BACKGROUND_TOP, _HKI( "Background gradient start color" ) ), + RR( _HKI( "Background End" ), LAYER_3D_BACKGROUND_BOTTOM, _HKI( "Background gradient end color" ) ), +}; + + +APPEARANCE_CONTROLS_3D::APPEARANCE_CONTROLS_3D( EDA_3D_VIEWER_FRAME* aParent, + wxWindow* aFocusOwner ) : + APPEARANCE_CONTROLS_3D_BASE( aParent ), + m_frame( aParent ), + m_focusOwner( aFocusOwner ) +{ + DPI_SCALING dpi( nullptr, m_frame ); + + int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x / dpi.GetContentScaleFactor(); + int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ); + m_pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize(); + + m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 ); + SetBorders( true, false, false, false ); + + m_layersOuterSizer = new wxBoxSizer( wxVERTICAL ); + m_windowLayers->SetSizer( m_layersOuterSizer ); + m_windowLayers->SetScrollRate( 0, 5 ); + m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS_3D::OnSetFocus, this ); + + m_envOuterSizer = new wxBoxSizer( wxVERTICAL ); + + wxFont infoFont = KIUI::GetInfoFont( this ); + m_panelLayers->SetFont( infoFont ); + m_windowLayers->SetFont( infoFont ); + m_presetsLabel->SetFont( infoFont ); + m_viewportsLabel->SetFont( infoFont ); + + m_cbLayerPresets->SetToolTip( wxString::Format( _( "Save and restore color and visibility " + "combinations.\n" + "Use %s+Tab to activate selector.\n" + "Successive Tabs while holding %s down will " + "cycle through presets in the popup." ), + KeyNameFromKeyCode( PRESET_SWITCH_KEY ), + KeyNameFromKeyCode( PRESET_SWITCH_KEY ) ) ); + + m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore camera position and zoom.\n" + "Use %s+Tab to activate selector.\n" + "Successive Tabs while holding %s down will " + "cycle through viewports in the popup." ), + KeyNameFromKeyCode( VIEWPORT_SWITCH_KEY ), + KeyNameFromKeyCode( VIEWPORT_SWITCH_KEY ) ) ); + + if( screenHeight <= 900 && m_pointSize >= indicatorSize ) + m_pointSize = m_pointSize * 8 / 10; + + m_cbLayerPresets->Bind( wxEVT_CHOICE, &APPEARANCE_CONTROLS_3D::onLayerPresetChanged, this ); + + m_toggleGridRenderer = new GRID_BITMAP_TOGGLE_RENDERER( KiBitmap( BITMAPS::visibility ), + KiBitmap( BITMAPS::visibility_off ) ); +} + + +APPEARANCE_CONTROLS_3D::~APPEARANCE_CONTROLS_3D() +{ +} + + +wxSize APPEARANCE_CONTROLS_3D::GetBestSize() const +{ + DPI_SCALING dpi( nullptr, m_frame ); + wxSize size( 220 * dpi.GetScaleFactor(), 480 * dpi.GetScaleFactor() ); + return size; +} + + +void APPEARANCE_CONTROLS_3D::OnSetFocus( wxFocusEvent& aEvent ) +{ +#ifdef __WXMSW__ + // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the + // focus and give it back to the parent in the button event handler. + if( wxBitmapButton* btn = dynamic_cast( aEvent.GetEventObject() ) ) + { + wxCommandEvent evt( wxEVT_BUTTON ); + wxPostEvent( btn, evt ); + } +#endif + + passOnFocus(); + aEvent.Skip(); +} + + +void APPEARANCE_CONTROLS_3D::OnSize( wxSizeEvent& aEvent ) +{ + aEvent.Skip(); +} + + +void APPEARANCE_CONTROLS_3D::OnLanguageChanged() +{ + Freeze(); + rebuildLayers(); + rebuildLayerPresetsWidget(); + rebuildViewportsWidget(); + + Thaw(); + Refresh(); +} + + +void APPEARANCE_CONTROLS_3D::OnDarkModeToggle() +{ + // This is essentially a list of hacks because DarkMode isn't yet implemented inside + // wxWidgets. + // + // The individual wxPanels, COLOR_SWATCHes and GRID_CELL_COLOR_RENDERERs should really be + // overriding some virtual method or responding to some wxWidgets event so that the parent + // doesn't have to know what it contains. But, that's not where we are, so... :shrug: + + m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 ); + + m_windowLayers->SetBackgroundColour( m_layerPanelColour ); + + for( wxSizerItem* child : m_layersOuterSizer->GetChildren() ) + { + if( child && child->GetWindow() ) + child->GetWindow()->SetBackgroundColour( m_layerPanelColour ); + } +} + + +void APPEARANCE_CONTROLS_3D::CommonSettingsChanged() +{ + OnLanguageChanged(); +} + + +void APPEARANCE_CONTROLS_3D::ApplyLayerPreset( const wxString& aPresetName ) +{ + if( aPresetName == FOLLOW_PCB || aPresetName == FOLLOW_PLOT_SETTINGS ) + { + m_frame->GetAdapter().m_Cfg->m_CurrentPreset = aPresetName; + UpdateLayerCtls(); + m_frame->NewDisplay( true ); + } + else if( LAYER_PRESET_3D* preset = m_frame->GetAdapter().m_Cfg->FindPreset( aPresetName ) ) + { + doApplyLayerPreset( *preset ); + } + + // Move to front of MRU list + if( m_presetMRU.Index( aPresetName ) != wxNOT_FOUND ) + m_presetMRU.Remove( aPresetName ); + + m_presetMRU.Insert( aPresetName, 0 ); + + updateLayerPresetWidget( aPresetName ); +} + + +std::vector APPEARANCE_CONTROLS_3D::GetUserViewports() const +{ + std::vector ret; + + for( const auto& [name, viewport] : m_viewports ) + ret.emplace_back( viewport ); + + return ret; +} + + +void APPEARANCE_CONTROLS_3D::SetUserViewports( std::vector& aViewportList ) +{ + m_viewports.clear(); + + for( const VIEWPORT3D& viewport : aViewportList ) + { + if( m_viewports.count( viewport.name ) ) + continue; + + m_viewports[viewport.name] = viewport; + + m_viewportMRU.Add( viewport.name ); + } + + rebuildViewportsWidget(); + + // Now is as good a time as any to initialize the layer presets as well. + rebuildLayerPresetsWidget(); + + m_presetMRU.Add( FOLLOW_PCB ); + m_presetMRU.Add( FOLLOW_PLOT_SETTINGS ); + + for( const LAYER_PRESET_3D& preset : m_frame->GetAdapter().m_Cfg->m_LayerPresets ) + m_presetMRU.Add( preset.name ); +} + + +void APPEARANCE_CONTROLS_3D::ApplyViewport( const wxString& aViewportName ) +{ + int idx = m_cbViewports->FindString( aViewportName ); + + if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ ) + { + m_cbViewports->SetSelection( idx ); + m_lastSelectedViewport = static_cast( m_cbViewports->GetClientData( idx ) ); + } + else + { + m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator + m_lastSelectedViewport = nullptr; + } + + if( m_lastSelectedViewport ) + doApplyViewport( *m_lastSelectedViewport ); +} + + +void APPEARANCE_CONTROLS_3D::OnLayerVisibilityChanged( int aLayer, bool isVisible ) +{ + std::bitset visibleLayers = m_frame->GetAdapter().GetVisibleLayers(); + const std::map& colors = m_frame->GetAdapter().GetLayerColors(); + bool killFollow = false; + + // Special-case controls + switch( aLayer ) + { + case LAYER_FP_TEXT: + // Because Footprint Text is a meta-control that also can disable values/references, + // drag them along here so that the user is less likely to be confused. + visibleLayers.set( LAYER_FP_REFERENCES, isVisible ); + visibleLayers.set( LAYER_FP_VALUES, isVisible ); + visibleLayers.set( LAYER_FP_TEXT, isVisible ); + killFollow = true; + break; + + case LAYER_FP_REFERENCES: + case LAYER_FP_VALUES: + // In case that user changes Footprint Value/References when the Footprint Text + // meta-control is disabled, we should put it back on. + if( isVisible ) + OnLayerVisibilityChanged( LAYER_FP_TEXT, isVisible ); + + visibleLayers.set( aLayer, isVisible ); + killFollow = true; + break; + + case LAYER_3D_COPPER_TOP: + case LAYER_3D_COPPER_BOTTOM: + case LAYER_3D_SILKSCREEN_BOTTOM: + case LAYER_3D_SILKSCREEN_TOP: + case LAYER_3D_SOLDERMASK_BOTTOM: + case LAYER_3D_SOLDERMASK_TOP: + case LAYER_3D_SOLDERPASTE: + case LAYER_3D_ADHESIVE: + case LAYER_3D_USER_COMMENTS: + case LAYER_3D_USER_DRAWINGS: + case LAYER_3D_USER_ECO1: + case LAYER_3D_USER_ECO2: + visibleLayers.set( aLayer, isVisible ); + killFollow = true; + break; + + default: + visibleLayers.set( aLayer, isVisible ); + break; + } + + m_frame->GetAdapter().SetVisibleLayers( visibleLayers ); + m_frame->GetAdapter().SetLayerColors( colors ); + + const wxString& currentPreset = m_frame->GetAdapter().m_Cfg->m_CurrentPreset; + + if( ( currentPreset != FOLLOW_PCB && currentPreset != FOLLOW_PLOT_SETTINGS ) || killFollow ) + syncLayerPresetSelection(); + + UpdateLayerCtls(); + m_frame->NewDisplay( true ); +} + + +void APPEARANCE_CONTROLS_3D::onColorSwatchChanged( COLOR_SWATCH* aSwatch ) +{ + std::bitset visibleLayers = m_frame->GetAdapter().GetVisibleLayers(); + std::map colors = m_frame->GetAdapter().GetLayerColors(); + + m_frame->GetAdapter().SetVisibleLayers( visibleLayers ); + m_frame->GetAdapter().SetLayerColors( colors ); + + int layer = aSwatch->GetId(); + COLOR4D newColor = aSwatch->GetSwatchColor(); + + colors[ layer ] = newColor; + + if( layer == LAYER_3D_COPPER_TOP ) + colors[ LAYER_3D_COPPER_BOTTOM ] = newColor; + else if( layer == LAYER_3D_COPPER_BOTTOM ) + colors[ LAYER_3D_COPPER_TOP ] = newColor; + + m_frame->GetAdapter().SetLayerColors( colors ); + + syncLayerPresetSelection(); + + m_frame->NewDisplay( true ); +} + + +void APPEARANCE_CONTROLS_3D::rebuildLayers() +{ + int swatchWidth = m_windowLayers->ConvertDialogToPixels( wxSize( 8, 0 ) ).x; + + std::bitset visibleLayers = m_frame->GetAdapter().GetVisibleLayers(); + std::map colors = m_frame->GetAdapter().GetLayerColors(); + std::map defaultColors = m_frame->GetAdapter().GetDefaultColors(); + + m_layerSettings.clear(); + m_layersOuterSizer->Clear( true ); + m_layersOuterSizer->AddSpacer( 5 ); + + m_envOuterSizer->Clear( true ); + + auto appendLayer = + [&]( const std::unique_ptr& aSetting ) + { + wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL ); + int layer = aSetting->id; + + aSetting->visible = visibleLayers.test( layer ); + + if( colors.count( layer ) ) + { + COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowLayers, colors[ layer ], layer, + COLOR4D::WHITE, defaultColors[ layer ], + SWATCH_SMALL ); + swatch->SetToolTip( _( "Left double click or middle click for color change, " + "right click for menu" ) ); + + sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 ); + aSetting->ctl_color = swatch; + + swatch->Bind( COLOR_SWATCH_CHANGED, + [this]( wxCommandEvent& event ) + { + auto swatch = static_cast( event.GetEventObject() ); + onColorSwatchChanged( swatch ); + + passOnFocus(); + } ); + } + else + { + sizer->AddSpacer( swatchWidth ); + } + + sizer->AddSpacer( 5 ); + + wxStaticText* label = new wxStaticText( m_windowLayers, layer, aSetting->label ); + label->Wrap( -1 ); + label->SetToolTip( aSetting->tooltip ); + + if( layer == LAYER_3D_BACKGROUND_TOP || layer == LAYER_3D_BACKGROUND_BOTTOM ) + { + sizer->AddSpacer( swatchWidth ); + } + else + { + BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowLayers, layer, + KiBitmap( BITMAPS::visibility ), + KiBitmap( BITMAPS::visibility_off ), + aSetting->visible ); + + btn_visible->Bind( TOGGLE_CHANGED, + [this]( wxCommandEvent& aEvent ) + { + int id = static_cast( aEvent.GetEventObject() )->GetId(); + bool isVisible = aEvent.GetInt(); + OnLayerVisibilityChanged( id, isVisible ); + + passOnFocus(); + } ); + + wxString tip; + tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() ); + btn_visible->SetToolTip( tip ); + + aSetting->ctl_visibility = btn_visible; + sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 ); + } + + sizer->AddSpacer( 5 ); + sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 ); + + m_layersOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 ); + m_layersOuterSizer->AddSpacer( 2 ); + }; + + for( const APPEARANCE_SETTING_3D& s_setting : s_layerSettings ) + { + m_layerSettings.emplace_back( std::make_unique( s_setting ) ); + std::unique_ptr& setting = m_layerSettings.back(); + + // Because s_render_rows is created static, we must explicitly call wxGetTranslation + // for texts which are internationalized (tool tips and item names) + setting->tooltip = wxGetTranslation( s_setting.tooltip ); + setting->label = wxGetTranslation( s_setting.label ); + + if( setting->spacer ) + m_layersOuterSizer->AddSpacer( m_pointSize ); + else + appendLayer( setting ); + + m_layerSettingsMap[setting->id] = setting.get(); + } + + m_sizerOuter->Layout(); +} + + +void APPEARANCE_CONTROLS_3D::UpdateLayerCtls() +{ + std::bitset visibleLayers = m_frame->GetAdapter().GetVisibleLayers(); + std::map colors = m_frame->GetAdapter().GetLayerColors(); + + for( std::unique_ptr& setting : m_layerSettings ) + { + if( setting->spacer ) + continue; + + if( setting->ctl_visibility ) + setting->ctl_visibility->SetValue( visibleLayers.test( setting->id ) ); + + if( setting->ctl_color ) + setting->ctl_color->SetSwatchColor( colors[ setting->id ], false ); + } +} + + +void APPEARANCE_CONTROLS_3D::rebuildLayerPresetsWidget() +{ + m_viewportsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ), + KeyNameFromKeyCode( PRESET_SWITCH_KEY ) ) ); + + m_cbLayerPresets->Clear(); + + // Build the layers preset list. + + m_cbLayerPresets->Append( _( "Follow PCB Editor" ) ); + m_cbLayerPresets->Append( _( "Follow PCB Plot Settings" ) ); + + for( const LAYER_PRESET_3D& preset : m_frame->GetAdapter().m_Cfg->m_LayerPresets ) + m_cbLayerPresets->Append( preset.name ); + + m_cbLayerPresets->Append( wxT( "---" ) ); + m_cbLayerPresets->Append( _( "Save preset..." ) ); + m_cbLayerPresets->Append( _( "Delete preset..." ) ); + + updateLayerPresetWidget( m_frame->GetAdapter().m_Cfg->m_CurrentPreset ); +} + + +void APPEARANCE_CONTROLS_3D::syncLayerPresetSelection() +{ + m_frame->GetAdapter().m_Cfg->m_CurrentPreset = wxEmptyString; + + std::vector& presets = m_frame->GetAdapter().m_Cfg->m_LayerPresets; + std::bitset visibleLayers = m_frame->GetAdapter().GetVisibleLayers(); + std::map colors = m_frame->GetAdapter().GetLayerColors(); + + auto it = std::find_if( presets.begin(), presets.end(), + [&]( const LAYER_PRESET_3D& aPreset ) + { + for( int layer = LAYER_3D_BOARD; layer < LAYER_3D_END; ++layer ) + { + if( aPreset.layers.test( layer ) != visibleLayers.test( layer ) ) + return false; + } + + for( int layer : { LAYER_FP_REFERENCES, LAYER_FP_VALUES, LAYER_FP_TEXT } ) + { + if( aPreset.layers.test( layer ) != visibleLayers.test( layer ) ) + return false; + } + + for( int layer = LAYER_3D_BOARD; layer < LAYER_3D_ADHESIVE; ++layer ) + { + if( aPreset.colors.at( layer ) != colors.at( layer ) ) + return false; + } + + return true; + } ); + + if( it != presets.end() ) + { + m_frame->GetAdapter().m_Cfg->m_CurrentPreset = it->name; + m_cbLayerPresets->SetStringSelection( it->name ); + } + else + { + m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator + } +} + + +void APPEARANCE_CONTROLS_3D::updateLayerPresetWidget( const wxString& aName ) +{ + if( aName == FOLLOW_PCB ) + m_cbLayerPresets->SetSelection( 0 ); + else if( aName == FOLLOW_PLOT_SETTINGS ) + m_cbLayerPresets->SetSelection( 1 ); + else if( !m_cbLayerPresets->SetStringSelection( aName ) ) + m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator +} + + +void APPEARANCE_CONTROLS_3D::onLayerPresetChanged( wxCommandEvent& aEvent ) +{ + EDA_3D_VIEWER_SETTINGS* cfg = m_frame->GetAdapter().m_Cfg; + int count = m_cbLayerPresets->GetCount(); + int index = m_cbLayerPresets->GetSelection(); + wxString name; + + if( index == 0 ) + { + name = FOLLOW_PCB; + cfg->m_CurrentPreset = name; + UpdateLayerCtls(); + m_frame->NewDisplay( true ); + } + else if( index == 1 ) + { + name = FOLLOW_PLOT_SETTINGS; + cfg->m_CurrentPreset = name; + UpdateLayerCtls(); + m_frame->NewDisplay( true ); + } + else if( index == count - 3 ) + { + // Separator: reject the selection + updateLayerPresetWidget( cfg->m_CurrentPreset ); + return; + } + else if( index == count - 2 ) + { + wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ) ); + + if( dlg.ShowModal() != wxID_OK ) + { + updateLayerPresetWidget( cfg->m_CurrentPreset ); + return; + } + else + { + std::bitset visibleLayers = m_frame->GetAdapter().GetVisibleLayers(); + std::map colors = m_frame->GetAdapter().GetLayerColors(); + + name = dlg.GetValue(); + + if( LAYER_PRESET_3D* preset = cfg->FindPreset( name ) ) + { + preset->layers = visibleLayers; + preset->colors = colors; + m_cbLayerPresets->SetSelection( m_cbLayerPresets->FindString( name ) ); + } + else + { + cfg->m_LayerPresets.emplace_back( name, visibleLayers, colors ); + m_cbLayerPresets->SetSelection( m_cbLayerPresets->Insert( name, index - 1 ) ); + } + + cfg->m_CurrentPreset = name; + } + } + else if( index == count - 1 ) + { + wxArrayString headers; + std::vector items; + + headers.Add( _( "Presets" ) ); + + for( LAYER_PRESET_3D& preset : cfg->m_LayerPresets ) + { + wxArrayString item; + item.Add( preset.name ); + items.emplace_back( item ); + } + + EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items ); + dlg.SetListLabel( _( "Select preset:" ) ); + + if( dlg.ShowModal() == wxID_OK ) + { + name = dlg.GetTextSelection(); + + if( m_cbLayerPresets->FindString( name ) != wxNOT_FOUND ) + m_cbLayerPresets->Delete( m_cbLayerPresets->FindString( name ) ); + + alg::delete_if( cfg->m_LayerPresets, + [name]( const LAYER_PRESET_3D& preset ) + { + return preset.name == name; + } ); + + if( cfg->m_CurrentPreset == name ) + cfg->m_CurrentPreset = wxEmptyString; + + m_presetMRU.Remove( name ); + } + + updateLayerPresetWidget( cfg->m_CurrentPreset ); + return; + } + else if( LAYER_PRESET_3D* preset = cfg->FindPreset( m_cbLayerPresets->GetStringSelection() ) ) + { + name = preset->name; + doApplyLayerPreset( *preset ); + } + + // Move to front of MRU list + if( m_presetMRU.Index( name ) != wxNOT_FOUND ) + m_presetMRU.Remove( name ); + + m_presetMRU.Insert( name, 0 ); + + passOnFocus(); +} + + +void APPEARANCE_CONTROLS_3D::doApplyLayerPreset( const LAYER_PRESET_3D& aPreset ) +{ + BOARD_ADAPTER& adapter = m_frame->GetAdapter(); + + adapter.m_Cfg->m_CurrentPreset = aPreset.name; + adapter.SetVisibleLayers( aPreset.layers ); + adapter.SetLayerColors( aPreset.colors ); + + UpdateLayerCtls(); + m_frame->NewDisplay( true ); +} + + +void APPEARANCE_CONTROLS_3D::rebuildViewportsWidget() +{ + m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ), + KeyNameFromKeyCode( VIEWPORT_SWITCH_KEY ) ) ); + + m_cbViewports->Clear(); + + for( std::pair& pair : m_viewports ) + m_cbViewports->Append( pair.first, static_cast( &pair.second ) ); + + m_cbViewports->Append( wxT( "---" ) ); + m_cbViewports->Append( _( "Save viewport..." ) ); + m_cbViewports->Append( _( "Delete viewport..." ) ); + + m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); + m_lastSelectedViewport = nullptr; +} + + +void APPEARANCE_CONTROLS_3D::onViewportChanged( wxCommandEvent& aEvent ) +{ + int count = m_cbViewports->GetCount(); + int index = m_cbViewports->GetSelection(); + + if( index >= 0 && index < count - 3 ) + { + VIEWPORT3D* viewport = static_cast( m_cbViewports->GetClientData( index ) ); + + wxCHECK( viewport, /* void */ ); + + doApplyViewport( *viewport ); + + if( !viewport->name.IsEmpty() ) + { + m_viewportMRU.Remove( viewport->name ); + m_viewportMRU.Insert( viewport->name, 0 ); + } + } + else if( index == count - 2 ) + { + // Save current state to new preset + wxString name; + + wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name ); + + if( dlg.ShowModal() != wxID_OK ) + { + if( m_lastSelectedViewport ) + m_cbViewports->SetStringSelection( m_lastSelectedViewport->name ); + else + m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); + + return; + } + + name = dlg.GetValue(); + bool exists = m_viewports.count( name ); + + if( !exists ) + { + m_viewports[name] = VIEWPORT3D( name, m_frame->GetCurrentCamera().GetViewMatrix() ); + + index = m_cbViewports->Insert( name, index-1, static_cast( &m_viewports[name] ) ); + } + else + { + m_viewports[name].matrix = m_frame->GetCurrentCamera().GetViewMatrix(); + index = m_cbViewports->FindString( name ); + m_viewportMRU.Remove( name ); + } + + m_cbViewports->SetSelection( index ); + m_viewportMRU.Insert( name, 0 ); + + return; + } + else if( index == count - 1 ) + { + // Delete an existing viewport + wxArrayString headers; + std::vector items; + + headers.Add( _( "Viewports" ) ); + + for( std::pair& pair : m_viewports ) + { + wxArrayString item; + item.Add( pair.first ); + items.emplace_back( item ); + } + + EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items ); + dlg.SetListLabel( _( "Select viewport:" ) ); + + if( dlg.ShowModal() == wxID_OK ) + { + wxString viewportName = dlg.GetTextSelection(); + int idx = m_cbViewports->FindString( viewportName ); + + if( idx != wxNOT_FOUND ) + { + m_viewports.erase( viewportName ); + m_cbViewports->Delete( idx ); + m_viewportMRU.Remove( viewportName ); + } + } + + if( m_lastSelectedViewport ) + m_cbViewports->SetStringSelection( m_lastSelectedViewport->name ); + else + m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); + + return; + } + + passOnFocus(); +} + + +void APPEARANCE_CONTROLS_3D::onUpdateViewportsCb( wxUpdateUIEvent& aEvent ) +{ + int count = m_cbViewports->GetCount(); + int index = m_cbViewports->GetSelection(); + + if( index >= 0 && index < count - 3 ) + { + VIEWPORT3D* viewport = static_cast( m_cbViewports->GetClientData( index ) ); + + wxCHECK( viewport, /* void */ ); + + if( m_frame->GetCurrentCamera().GetViewMatrix() != viewport->matrix ) + m_cbViewports->SetSelection( -1 ); + } +} + + +void APPEARANCE_CONTROLS_3D::doApplyViewport( const VIEWPORT3D& aViewport ) +{ + m_frame->GetCurrentCamera().SetViewMatrix( aViewport.matrix ); + + if( m_frame->GetAdapter().m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL ) + m_frame->GetCanvas()->Request_refresh(); + else + m_frame->GetCanvas()->RenderRaytracingRequest(); +} + + +void APPEARANCE_CONTROLS_3D::passOnFocus() +{ + m_focusOwner->SetFocus(); +} + + diff --git a/3d-viewer/dialogs/appearance_controls_3D.h b/3d-viewer/dialogs/appearance_controls_3D.h new file mode 100644 index 0000000000..8c1e291569 --- /dev/null +++ b/3d-viewer/dialogs/appearance_controls_3D.h @@ -0,0 +1,158 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 CERN + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef APPEARANCE_CONTROLS_3D_H +#define APPEARANCE_CONTROLS_3D_H + +#include + +#include +#include +#include <3d_canvas/board_adapter.h> +#include + + +class BITMAP_TOGGLE; +class COLOR_SWATCH; +class EDA_3D_VIEWER_FRAME; +class ROW_ICON_PROVIDER; +class GRID_BITMAP_TOGGLE_RENDERER; + +using KIGFX::COLOR4D; + + +class APPEARANCE_CONTROLS_3D : public APPEARANCE_CONTROLS_3D_BASE +{ +public: + + /** + * Container for an appearance setting (can control a layer class, object type, etc.) + */ + struct APPEARANCE_SETTING_3D + { + int id; + wxString label; + wxString tooltip; + bool visible; + bool spacer; + + BITMAP_TOGGLE* ctl_visibility; + COLOR_SWATCH* ctl_color; + + APPEARANCE_SETTING_3D( const wxString& aLabel, int aId, const wxString& aTooltip ) : + id( aId ), + label( aLabel ), + tooltip( aTooltip ), + visible( true ), + spacer( false ), + ctl_visibility( nullptr ), + ctl_color( nullptr ) + { + } + + APPEARANCE_SETTING_3D() : + id( -1 ), + visible( false ), + spacer( true ), + ctl_visibility( nullptr ), + ctl_color( nullptr ) + { + } + }; + + APPEARANCE_CONTROLS_3D( EDA_3D_VIEWER_FRAME* aParent, wxWindow* aFocusOwner ); + ~APPEARANCE_CONTROLS_3D(); + + wxSize GetBestSize() const; + + void OnLanguageChanged(); + void OnDarkModeToggle(); + void OnLayerVisibilityChanged( int aLayer, bool isVisible ); + + void CommonSettingsChanged(); + + void UpdateLayerCtls(); + + void ApplyLayerPreset( const wxString& aPresetName ); + + const wxArrayString& GetLayerPresetsMRU() { return m_presetMRU; } + + ///< Return a list of viewports created by the user. + std::vector GetUserViewports() const; + + ///< Update the current viewports from those saved in the project file. + void SetUserViewports( std::vector& aPresetList ); + + void ApplyViewport( const wxString& aPresetName ); + + const wxArrayString& GetViewportsMRU() { return m_viewportMRU; } + +protected: + void OnSetFocus( wxFocusEvent& aEvent ) override; + void OnSize( wxSizeEvent& aEvent ) override; + +private: + void rebuildLayers(); + + void rebuildLayerPresetsWidget(); + + void syncLayerPresetSelection(); + + void rebuildViewportsWidget(); + + void onColorSwatchChanged( COLOR_SWATCH* aSwatch ); + + void updateLayerPresetWidget( const wxString& aName ); + + void onLayerPresetChanged( wxCommandEvent& aEvent ) override; + + void doApplyLayerPreset( const LAYER_PRESET_3D& aPreset ); + + void onViewportChanged( wxCommandEvent& aEvent ) override; + void onUpdateViewportsCb( wxUpdateUIEvent& aEvent ) override; + + void doApplyViewport( const VIEWPORT3D& aViewport ); + + void passOnFocus(); + +private: + EDA_3D_VIEWER_FRAME* m_frame; + wxWindow* m_focusOwner; + + static const APPEARANCE_SETTING_3D s_layerSettings[]; + + GRID_BITMAP_TOGGLE_RENDERER* m_toggleGridRenderer; + + std::vector> m_layerSettings; + std::map m_layerSettingsMap; + + wxArrayString m_presetMRU; + + std::map m_viewports; + VIEWPORT3D* m_lastSelectedViewport; + wxArrayString m_viewportMRU; + + wxBoxSizer* m_layersOuterSizer; + wxBoxSizer* m_envOuterSizer; + int m_pointSize; + wxColour m_layerPanelColour; +}; + +#endif diff --git a/3d-viewer/dialogs/appearance_controls_3D_base.cpp b/3d-viewer/dialogs/appearance_controls_3D_base.cpp new file mode 100644 index 0000000000..0d51a66861 --- /dev/null +++ b/3d-viewer/dialogs/appearance_controls_3D_base.cpp @@ -0,0 +1,95 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "appearance_controls_3D_base.h" + +/////////////////////////////////////////////////////////////////////////// + +APPEARANCE_CONTROLS_3D_BASE::APPEARANCE_CONTROLS_3D_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : WX_PANEL( parent, id, pos, size, style, name ) +{ + this->SetMinSize( wxSize( 200,360 ) ); + + m_sizerOuter = new wxBoxSizer( wxVERTICAL ); + + m_panelLayers = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelLayersSizer = new wxBoxSizer( wxVERTICAL ); + + m_windowLayers = new wxScrolledCanvas( m_panelLayers, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL ); + m_panelLayersSizer->Add( m_windowLayers, 1, wxEXPAND, 5 ); + + + m_panelLayers->SetSizer( m_panelLayersSizer ); + m_panelLayers->Layout(); + m_panelLayersSizer->Fit( m_panelLayers ); + m_sizerOuter->Add( m_panelLayers, 1, wxEXPAND|wxBOTTOM, 5 ); + + wxBoxSizer* bBottomMargin; + bBottomMargin = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bPresets; + bPresets = new wxBoxSizer( wxVERTICAL ); + + m_presetsLabel = new wxStaticText( this, wxID_ANY, _("Presets (Ctrl+Tab):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_presetsLabel->Wrap( -1 ); + bPresets->Add( m_presetsLabel, 1, wxRIGHT|wxLEFT, 2 ); + + wxString m_cbLayerPresetsChoices[] = { _("Follow PCB Editor"), _("Follow PCB Plot Settings") }; + int m_cbLayerPresetsNChoices = sizeof( m_cbLayerPresetsChoices ) / sizeof( wxString ); + m_cbLayerPresets = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cbLayerPresetsNChoices, m_cbLayerPresetsChoices, 0 ); + m_cbLayerPresets->SetSelection( 1 ); + bPresets->Add( m_cbLayerPresets, 0, wxALL|wxEXPAND, 2 ); + + + bBottomMargin->Add( bPresets, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + + bBottomMargin->Add( 0, 2, 0, wxEXPAND, 5 ); + + wxBoxSizer* bViewports; + bViewports = new wxBoxSizer( wxVERTICAL ); + + m_viewportsLabel = new wxStaticText( this, wxID_ANY, _("Viewports (Alt+Tab):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_viewportsLabel->Wrap( -1 ); + bViewports->Add( m_viewportsLabel, 1, wxRIGHT|wxLEFT, 2 ); + + wxString m_cbViewportsChoices[] = { _("(unsaved)") }; + int m_cbViewportsNChoices = sizeof( m_cbViewportsChoices ) / sizeof( wxString ); + m_cbViewports = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cbViewportsNChoices, m_cbViewportsChoices, 0 ); + m_cbViewports->SetSelection( 1 ); + bViewports->Add( m_cbViewports, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 2 ); + + + bBottomMargin->Add( bViewports, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + m_sizerOuter->Add( bBottomMargin, 0, wxEXPAND|wxTOP|wxBOTTOM, 2 ); + + + this->SetSizer( m_sizerOuter ); + this->Layout(); + m_sizerOuter->Fit( this ); + + // Connect Events + this->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( APPEARANCE_CONTROLS_3D_BASE::OnSetFocus ) ); + this->Connect( wxEVT_SIZE, wxSizeEventHandler( APPEARANCE_CONTROLS_3D_BASE::OnSize ) ); + m_panelLayers->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( APPEARANCE_CONTROLS_3D_BASE::OnSetFocus ), NULL, this ); + m_cbLayerPresets->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( APPEARANCE_CONTROLS_3D_BASE::onLayerPresetChanged ), NULL, this ); + m_cbViewports->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( APPEARANCE_CONTROLS_3D_BASE::onViewportChanged ), NULL, this ); + m_cbViewports->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( APPEARANCE_CONTROLS_3D_BASE::onUpdateViewportsCb ), NULL, this ); +} + +APPEARANCE_CONTROLS_3D_BASE::~APPEARANCE_CONTROLS_3D_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( APPEARANCE_CONTROLS_3D_BASE::OnSetFocus ) ); + this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( APPEARANCE_CONTROLS_3D_BASE::OnSize ) ); + m_panelLayers->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( APPEARANCE_CONTROLS_3D_BASE::OnSetFocus ), NULL, this ); + m_cbLayerPresets->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( APPEARANCE_CONTROLS_3D_BASE::onLayerPresetChanged ), NULL, this ); + m_cbViewports->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( APPEARANCE_CONTROLS_3D_BASE::onViewportChanged ), NULL, this ); + m_cbViewports->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( APPEARANCE_CONTROLS_3D_BASE::onUpdateViewportsCb ), NULL, this ); + +} diff --git a/3d-viewer/dialogs/appearance_controls_3D_base.fbp b/3d-viewer/dialogs/appearance_controls_3D_base.fbp new file mode 100644 index 0000000000..a729c41405 --- /dev/null +++ b/3d-viewer/dialogs/appearance_controls_3D_base.fbp @@ -0,0 +1,487 @@ + + + + + ; + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + appearance_controls_3D_base + 1000 + none + + + 1 + Appearance Panel 3D + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + 1 + 1 + impl_virtual + + + 0 + wxID_ANY + + 200,360 + APPEARANCE_CONTROLS_3D_BASE + + -1,-1 + WX_PANEL; widgets/wx_panel.h; forward_declare + + 0 + + + wxTAB_TRAVERSAL + OnSetFocus + OnSize + + + m_sizerOuter + wxVERTICAL + protected + + 5 + wxEXPAND|wxBOTTOM + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panelLayers + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + OnSetFocus + + + m_panelLayersSizer + wxVERTICAL + protected + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + wxScrolledCanvas + 1 + + + 1 + + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + #include <wx/scrolwin.h> + + 0 + + + 0 + + 1 + m_windowLayers + 1 + + + protected + 1 + + Resizable + + 1 + + ; ; forward_declare + 0 + + + + wxVSCROLL + + + + + + + 2 + wxEXPAND|wxTOP|wxBOTTOM + 0 + + + bBottomMargin + wxVERTICAL + none + + 5 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + + bPresets + wxVERTICAL + none + + 2 + wxRIGHT|wxLEFT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Presets (Ctrl+Tab): + 0 + + 0 + + + 0 + + 1 + m_presetsLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 2 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Follow PCB Editor" "Follow PCB Plot Settings" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_cbLayerPresets + 1 + + + protected + 1 + + Resizable + 1 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onLayerPresetChanged + + + + + + 5 + wxEXPAND + 0 + + 2 + protected + 0 + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 1 + + + bViewports + wxVERTICAL + none + + 2 + wxRIGHT|wxLEFT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Viewports (Alt+Tab): + 0 + + 0 + + + 0 + + 1 + m_viewportsLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 2 + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "(unsaved)" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_cbViewports + 1 + + + protected + 1 + + Resizable + 1 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onViewportChanged + onUpdateViewportsCb + + + + + + + + + + diff --git a/3d-viewer/dialogs/appearance_controls_3D_base.h b/3d-viewer/dialogs/appearance_controls_3D_base.h new file mode 100644 index 0000000000..5d91512e24 --- /dev/null +++ b/3d-viewer/dialogs/appearance_controls_3D_base.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include "widgets/wx_panel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class APPEARANCE_CONTROLS_3D_BASE +/////////////////////////////////////////////////////////////////////////////// +class APPEARANCE_CONTROLS_3D_BASE : public WX_PANEL +{ + private: + + protected: + wxBoxSizer* m_sizerOuter; + wxPanel* m_panelLayers; + wxBoxSizer* m_panelLayersSizer; + wxScrolledCanvas* m_windowLayers; + wxStaticText* m_presetsLabel; + wxChoice* m_cbLayerPresets; + wxStaticText* m_viewportsLabel; + wxChoice* m_cbViewports; + + // Virtual event handlers, override them in your derived class + virtual void OnSetFocus( wxFocusEvent& event ) { event.Skip(); } + virtual void OnSize( wxSizeEvent& event ) { event.Skip(); } + virtual void onLayerPresetChanged( wxCommandEvent& event ) { event.Skip(); } + virtual void onViewportChanged( wxCommandEvent& event ) { event.Skip(); } + virtual void onUpdateViewportsCb( wxUpdateUIEvent& event ) { event.Skip(); } + + + public: + + 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 ); + + ~APPEARANCE_CONTROLS_3D_BASE(); + +}; + diff --git a/3d-viewer/dialogs/panel_3D_colors.cpp b/3d-viewer/dialogs/panel_3D_colors.cpp index 54bf291c62..2dbd1448c8 100644 --- a/3d-viewer/dialogs/panel_3D_colors.cpp +++ b/3d-viewer/dialogs/panel_3D_colors.cpp @@ -33,9 +33,9 @@ PANEL_3D_COLORS::PANEL_3D_COLORS( wxWindow* aParent ) : m_backgroundTop->SetDefaultColor( BOARD_ADAPTER::g_DefaultBackgroundTop ); m_backgroundBottom->SetDefaultColor( BOARD_ADAPTER::g_DefaultBackgroundBot ); - m_silkscreenTop->SetUserColors( &BOARD_ADAPTER::g_SilkscreenColors ); + m_silkscreenTop->SetUserColors( &BOARD_ADAPTER::g_SilkColors ); m_silkscreenTop->SetDefaultColor( BOARD_ADAPTER::g_DefaultSilkscreen ); - m_silkscreenBottom->SetUserColors( &BOARD_ADAPTER::g_SilkscreenColors ); + m_silkscreenBottom->SetUserColors( &BOARD_ADAPTER::g_SilkColors ); m_silkscreenBottom->SetDefaultColor( BOARD_ADAPTER::g_DefaultSilkscreen ); m_solderMaskTop->SetUserColors( &BOARD_ADAPTER::g_MaskColors ); @@ -75,7 +75,7 @@ bool PANEL_3D_COLORS::TransferDataToWindow() m_solderMaskTop->SetSwatchColor( colors->GetColor( LAYER_3D_SOLDERMASK_TOP ), false ); m_solderMaskBottom->SetSwatchColor( colors->GetColor( LAYER_3D_SOLDERMASK_BOTTOM ), false ); m_solderPaste->SetSwatchColor( colors->GetColor( LAYER_3D_SOLDERPASTE ), false ); - m_surfaceFinish->SetSwatchColor( colors->GetColor( LAYER_3D_COPPER ), false ); + m_surfaceFinish->SetSwatchColor( colors->GetColor( LAYER_3D_COPPER_TOP ), false ); m_boardBody->SetSwatchColor( colors->GetColor( LAYER_3D_BOARD ), false ); if( colors->GetUseBoardStackupColors() ) @@ -98,7 +98,8 @@ bool PANEL_3D_COLORS::TransferDataFromWindow() colors->SetColor( LAYER_3D_SOLDERMASK_TOP, m_solderMaskTop->GetSwatchColor() ); colors->SetColor( LAYER_3D_SOLDERMASK_BOTTOM, m_solderMaskBottom->GetSwatchColor() ); colors->SetColor( LAYER_3D_SOLDERPASTE, m_solderPaste->GetSwatchColor() ); - colors->SetColor( LAYER_3D_COPPER, m_surfaceFinish->GetSwatchColor() ); + colors->SetColor( LAYER_3D_COPPER_TOP, m_surfaceFinish->GetSwatchColor() ); + colors->SetColor( LAYER_3D_COPPER_BOTTOM, m_surfaceFinish->GetSwatchColor() ); colors->SetColor( LAYER_3D_BOARD, m_boardBody->GetSwatchColor() ); colors->SetUseBoardStackupColors( m_boardStackupRB->GetValue() ); @@ -120,7 +121,7 @@ void PANEL_3D_COLORS::ResetPanel() m_solderMaskTop->SetSwatchColor( colors->GetDefaultColor( LAYER_3D_SOLDERMASK_TOP ), false ); m_solderMaskBottom->SetSwatchColor( colors->GetDefaultColor( LAYER_3D_SOLDERMASK_BOTTOM ), false ); m_solderPaste->SetSwatchColor( colors->GetDefaultColor( LAYER_3D_SOLDERPASTE ), false ); - m_surfaceFinish->SetSwatchColor( colors->GetDefaultColor( LAYER_3D_COPPER ), false ); + m_surfaceFinish->SetSwatchColor( colors->GetDefaultColor( LAYER_3D_COPPER_TOP ), false ); m_boardBody->SetSwatchColor( colors->GetDefaultColor( LAYER_3D_BOARD ), false ); m_boardStackupRB->SetValue( true ); diff --git a/3d-viewer/dialogs/panel_3D_display_options.cpp b/3d-viewer/dialogs/panel_3D_display_options.cpp index 9307b18f86..0c71a7f5f1 100644 --- a/3d-viewer/dialogs/panel_3D_display_options.cpp +++ b/3d-viewer/dialogs/panel_3D_display_options.cpp @@ -48,12 +48,30 @@ void PANEL_3D_DISPLAY_OPTIONS::loadViewSettings( EDA_3D_VIEWER_SETTINGS* aCfg ) m_checkBoxRealisticMode->SetValue( aCfg->m_Render.realistic ); m_checkBoxBoardBody->SetValue( aCfg->m_Render.show_board_body ); m_checkBoxAreas->SetValue( aCfg->m_Render.show_zones ); - m_checkBoxSilkscreen->SetValue( aCfg->m_Render.show_silkscreen ); - m_checkBoxSolderMask->SetValue( aCfg->m_Render.show_soldermask ); + + if( aCfg->m_Render.show_silkscreen_top == aCfg->m_Render.show_silkscreen_bottom ) + m_checkBoxSilkscreen->SetValue( aCfg->m_Render.show_silkscreen_top ); + else + m_checkBoxSilkscreen->Set3StateValue( wxCHK_UNDETERMINED ); + + if( aCfg->m_Render.show_soldermask_top == aCfg->m_Render.show_soldermask_bottom ) + m_checkBoxSolderMask->SetValue( aCfg->m_Render.show_soldermask_top ); + else + m_checkBoxSolderMask->Set3StateValue( wxCHK_UNDETERMINED ); + m_checkBoxSolderpaste->SetValue( aCfg->m_Render.show_solderpaste ); m_checkBoxAdhesive->SetValue( aCfg->m_Render.show_adhesive ); - m_checkBoxComments->SetValue( aCfg->m_Render.show_comments ); - m_checkBoxECO->SetValue( aCfg->m_Render.show_eco ); + + if( aCfg->m_Render.show_comments == aCfg->m_Render.show_drawings ) + m_checkBoxComments->SetValue( aCfg->m_Render.show_comments ); + else + m_checkBoxComments->Set3StateValue( wxCHK_UNDETERMINED ); + + if( aCfg->m_Render.show_eco1 == aCfg->m_Render.show_eco2 ) + m_checkBoxECO->SetValue( aCfg->m_Render.show_eco1 ); + else + m_checkBoxECO->Set3StateValue( wxCHK_UNDETERMINED ); + m_checkBoxSubtractMaskFromSilk->SetValue( aCfg->m_Render.subtract_mask_from_silk ); m_checkBoxClipSilkOnViaAnnulus->SetValue( aCfg->m_Render.clip_silk_on_via_annulus ); m_checkBoxRenderPlatedPadsAsPlated->SetValue( aCfg->m_Render.renderPlatedPadsAsPlated ); @@ -96,12 +114,32 @@ bool PANEL_3D_DISPLAY_OPTIONS::TransferDataFromWindow() cfg->m_Render.material_mode = static_cast( m_materialProperties->GetSelection() ); // Set Layer visibility - cfg->m_Render.show_silkscreen = m_checkBoxSilkscreen->GetValue(); - cfg->m_Render.show_soldermask = m_checkBoxSolderMask->GetValue(); + if( m_checkBoxSilkscreen->Get3StateValue() != wxCHK_UNDETERMINED ) + { + cfg->m_Render.show_silkscreen_top = m_checkBoxSilkscreen->GetValue(); + cfg->m_Render.show_silkscreen_bottom = m_checkBoxSilkscreen->GetValue(); + } + + if( m_checkBoxSolderMask->Get3StateValue() != wxCHK_UNDETERMINED ) + { + cfg->m_Render.show_soldermask_top = m_checkBoxSolderMask->GetValue(); + cfg->m_Render.show_soldermask_bottom = m_checkBoxSolderMask->GetValue(); + } + cfg->m_Render.show_solderpaste = m_checkBoxSolderpaste->GetValue(); cfg->m_Render.show_adhesive = m_checkBoxAdhesive->GetValue(); - cfg->m_Render.show_comments = m_checkBoxComments->GetValue(); - cfg->m_Render.show_eco = m_checkBoxECO->GetValue( ); + + if( m_checkBoxComments->Get3StateValue() != wxCHK_UNDETERMINED ) + { + cfg->m_Render.show_comments = m_checkBoxComments->GetValue(); + cfg->m_Render.show_drawings = m_checkBoxComments->GetValue(); + } + + if( m_checkBoxECO->Get3StateValue() != wxCHK_UNDETERMINED ) + { + cfg->m_Render.show_eco1 = m_checkBoxECO->GetValue( ); + cfg->m_Render.show_eco2 = m_checkBoxECO->GetValue( ); + } // Camera Options cfg->m_Camera.animation_enabled = m_checkBoxEnableAnimation->GetValue(); diff --git a/3d-viewer/dialogs/panel_3D_display_options_base.cpp b/3d-viewer/dialogs/panel_3D_display_options_base.cpp index fe0f77ef6e..97093b3685 100644 --- a/3d-viewer/dialogs/panel_3D_display_options_base.cpp +++ b/3d-viewer/dialogs/panel_3D_display_options_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb) +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -32,7 +32,7 @@ PANEL_3D_DISPLAY_OPTIONS_BASE::PANEL_3D_DISPLAY_OPTIONS_BASE( wxWindow* parent, fgSizer1->SetFlexibleDirection( wxBOTH ); fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_checkBoxSilkscreen = new wxCheckBox( this, wxID_ANY, _("Show silkscreen layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxSilkscreen = new wxCheckBox( this, wxID_ANY, _("Show silkscreen layers"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE ); fgSizer1->Add( m_checkBoxSilkscreen, 0, wxLEFT, 5 ); m_checkBoxSubtractMaskFromSilk = new wxCheckBox( this, wxID_ANY, _("Clip silkscreen at solder mask edges"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -41,7 +41,7 @@ PANEL_3D_DISPLAY_OPTIONS_BASE::PANEL_3D_DISPLAY_OPTIONS_BASE( wxWindow* parent, m_checkBoxClipSilkOnViaAnnulus = new wxCheckBox( this, wxID_ANY, _("Clip silkscreen at via annuli"), wxDefaultPosition, wxDefaultSize, 0 ); fgSizer1->Add( m_checkBoxClipSilkOnViaAnnulus, 0, wxLEFT, 25 ); - m_checkBoxSolderMask = new wxCheckBox( this, wxID_ANY, _("Show solder mask layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxSolderMask = new wxCheckBox( this, wxID_ANY, _("Show solder mask layers"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE ); fgSizer1->Add( m_checkBoxSolderMask, 0, wxTOP|wxLEFT, 5 ); m_checkBoxSolderpaste = new wxCheckBox( this, wxID_ANY, _("Show solder paste layers"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -56,7 +56,7 @@ PANEL_3D_DISPLAY_OPTIONS_BASE::PANEL_3D_DISPLAY_OPTIONS_BASE( wxWindow* parent, bSizeLeft->Add( 0, 15, 0, wxEXPAND, 5 ); - m_userLayersLabel = new wxStaticText( this, wxID_ANY, _("User Layers (not shown in realistic mode)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_userLayersLabel = new wxStaticText( this, wxID_ANY, _("User Layers"), wxDefaultPosition, wxDefaultSize, 0 ); m_userLayersLabel->Wrap( -1 ); bSizeLeft->Add( m_userLayersLabel, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 13 ); @@ -66,13 +66,13 @@ PANEL_3D_DISPLAY_OPTIONS_BASE::PANEL_3D_DISPLAY_OPTIONS_BASE( wxWindow* parent, bSizeLeft->Add( 0, 5, 0, wxEXPAND, 5 ); - m_checkBoxComments = new wxCheckBox( this, wxID_ANY, _("Show comment and drawing layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxComments = new wxCheckBox( this, wxID_ANY, _("Show comment and drawing layers"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE ); bSizeLeft->Add( m_checkBoxComments, 0, wxRIGHT|wxLEFT, 10 ); bSizeLeft->Add( 0, 4, 0, wxEXPAND, 5 ); - m_checkBoxECO = new wxCheckBox( this, wxID_ANY, _("Show ECO layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxECO = new wxCheckBox( this, wxID_ANY, _("Show ECO layers"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE ); bSizeLeft->Add( m_checkBoxECO, 0, wxRIGHT|wxLEFT, 10 ); diff --git a/3d-viewer/dialogs/panel_3D_display_options_base.fbp b/3d-viewer/dialogs/panel_3D_display_options_base.fbp index 25c69b0383..c701d896e3 100644 --- a/3d-viewer/dialogs/panel_3D_display_options_base.fbp +++ b/3d-viewer/dialogs/panel_3D_display_options_base.fbp @@ -261,7 +261,7 @@ Resizable 1 - + wxCHK_3STATE 0 @@ -453,7 +453,7 @@ Resizable 1 - + wxCHK_3STATE 0 @@ -638,7 +638,7 @@ 0 0 wxID_ANY - User Layers (not shown in realistic mode) + User Layers 0 0 @@ -786,7 +786,7 @@ Resizable 1 - + wxCHK_3STATE 0 @@ -860,7 +860,7 @@ Resizable 1 - + wxCHK_3STATE 0 diff --git a/3d-viewer/dialogs/panel_3D_display_options_base.h b/3d-viewer/dialogs/panel_3D_display_options_base.h index db1242f600..217cd58109 100644 --- a/3d-viewer/dialogs/panel_3D_display_options_base.h +++ b/3d-viewer/dialogs/panel_3D_display_options_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb) +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! diff --git a/3d-viewer/dialogs/panel_preview_3d_model.cpp b/3d-viewer/dialogs/panel_preview_3d_model.cpp index 55d77e3701..cd13d0f85b 100644 --- a/3d-viewer/dialogs/panel_preview_3d_model.cpp +++ b/3d-viewer/dialogs/panel_preview_3d_model.cpp @@ -216,30 +216,6 @@ void PANEL_PREVIEW_3D_MODEL::loadSettings() // TODO(JE) use all control options m_boardAdapter.m_MousewheelPanning = settings->m_Input.scroll_modifier_zoom != 0; - COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings(); - - if( colors ) - { - auto set = - [] ( const COLOR4D& aColor, SFVEC4F& aTarget ) - { - aTarget.r = aColor.r; - aTarget.g = aColor.g; - aTarget.b = aColor.b; - aTarget.a = aColor.a; - }; - - set( colors->GetColor( LAYER_3D_BACKGROUND_BOTTOM ), m_boardAdapter.m_BgColorBot ); - set( colors->GetColor( LAYER_3D_BACKGROUND_TOP ), m_boardAdapter.m_BgColorTop ); - set( colors->GetColor( LAYER_3D_BOARD ), m_boardAdapter.m_BoardBodyColor ); - set( colors->GetColor( LAYER_3D_COPPER ), m_boardAdapter.m_CopperColor ); - set( colors->GetColor( LAYER_3D_SILKSCREEN_BOTTOM ), m_boardAdapter.m_SilkScreenColorBot ); - set( colors->GetColor( LAYER_3D_SILKSCREEN_TOP ), m_boardAdapter.m_SilkScreenColorTop ); - set( colors->GetColor( LAYER_3D_SOLDERMASK_BOTTOM ), m_boardAdapter.m_SolderMaskColorBot ); - set( colors->GetColor( LAYER_3D_SOLDERMASK_TOP ), m_boardAdapter.m_SolderMaskColorTop ); - set( colors->GetColor( LAYER_3D_SOLDERPASTE ), m_boardAdapter.m_SolderPasteColor ); - } - EDA_3D_VIEWER_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings(); if( cfg ) @@ -254,7 +230,10 @@ void PANEL_PREVIEW_3D_MODEL::loadSettings() m_previewPane->SetProjectionMode( cfg->m_Camera.projection_mode ); // Ensure the board body is always shown, and do not use the settings of the 3D viewer - cfg->m_Render.show_soldermask = m_bodyStyleShowAll; + cfg->m_Render.show_copper_top = m_bodyStyleShowAll; + cfg->m_Render.show_copper_bottom = m_bodyStyleShowAll; + cfg->m_Render.show_soldermask_top = m_bodyStyleShowAll; + cfg->m_Render.show_soldermask_bottom = m_bodyStyleShowAll; cfg->m_Render.show_solderpaste = m_bodyStyleShowAll; cfg->m_Render.show_zones = m_bodyStyleShowAll; cfg->m_Render.show_board_body = m_bodyStyleShowAll; @@ -420,7 +399,8 @@ void PANEL_PREVIEW_3D_MODEL::setBodyStyleView( wxCommandEvent& event ) m_bodyStyleShowAll = !m_bodyStyleShowAll; - cfg->m_Render.show_soldermask = m_bodyStyleShowAll; + cfg->m_Render.show_soldermask_top = m_bodyStyleShowAll; + cfg->m_Render.show_soldermask_bottom = m_bodyStyleShowAll; cfg->m_Render.show_solderpaste = m_bodyStyleShowAll; cfg->m_Render.show_zones = m_bodyStyleShowAll; cfg->m_Render.show_board_body = m_bodyStyleShowAll; diff --git a/common/dialogs/eda_view_switcher.cpp b/common/dialogs/eda_view_switcher.cpp index e2e03bf825..d0793dcf5a 100644 --- a/common/dialogs/eda_view_switcher.cpp +++ b/common/dialogs/eda_view_switcher.cpp @@ -53,7 +53,8 @@ EDA_VIEW_SWITCHER::EDA_VIEW_SWITCHER( wxWindow* aParent, const wxArrayString& aI height += extents.y + LIST_BOX_V_PADDING; } - m_listBox->SetMinSize( wxSize( width + LIST_BOX_H_PADDING, height ) ); + m_listBox->SetMinSize( wxSize( width + LIST_BOX_H_PADDING, + height + ( LIST_BOX_V_PADDING * 2 ) ) ); SetInitialFocus( m_listBox ); // this line fixes an issue on Linux Ubuntu using Unity (dialog not shown), diff --git a/common/settings/builtin_color_themes.h b/common/settings/builtin_color_themes.h index 92f9641412..481ab4db13 100644 --- a/common/settings/builtin_color_themes.h +++ b/common/settings/builtin_color_themes.h @@ -234,7 +234,7 @@ static const std::map s_defaultTheme = { LAYER_3D_BACKGROUND_BOTTOM, COLOR4D( 0.4, 0.4, 0.5, 1.0 ) }, { LAYER_3D_BACKGROUND_TOP, COLOR4D( 0.8, 0.8, 0.9, 1.0 ) }, { LAYER_3D_BOARD, COLOR4D( 0.2, 0.17, 0.09, 0.9 ) }, - { LAYER_3D_COPPER, COLOR4D( 0.7, 0.61, 0.0, 1.0 ) }, + { LAYER_3D_COPPER_TOP, COLOR4D( 0.7, 0.61, 0.0, 1.0 ) }, { LAYER_3D_SILKSCREEN_BOTTOM, COLOR4D( 0.9, 0.9, 0.9, 1.0 ) }, { LAYER_3D_SILKSCREEN_TOP, COLOR4D( 0.9, 0.9, 0.9, 1.0 ) }, { LAYER_3D_SOLDERMASK_BOTTOM, COLOR4D( 0.08, 0.2, 0.14, 0.83 ) }, @@ -451,7 +451,7 @@ static const std::map s_classicTheme = { LAYER_3D_BACKGROUND_BOTTOM, COLOR4D( 0.4, 0.4, 0.5, 1.0 ) }, { LAYER_3D_BACKGROUND_TOP, COLOR4D( 0.8, 0.8, 0.9, 1.0 ) }, { LAYER_3D_BOARD, COLOR4D( 0.2, 0.17, 0.09, 0.9 ) }, - { LAYER_3D_COPPER, COLOR4D( 0.7, 0.61, 0.0, 1.0 ) }, + { LAYER_3D_COPPER_TOP, COLOR4D( 0.7, 0.61, 0.0, 1.0 ) }, { LAYER_3D_SILKSCREEN_BOTTOM, COLOR4D( 0.9, 0.9, 0.9, 1.0 ) }, { LAYER_3D_SILKSCREEN_TOP, COLOR4D( 0.9, 0.9, 0.9, 1.0 ) }, { LAYER_3D_SOLDERMASK_BOTTOM, COLOR4D( 0.08, 0.2, 0.14, 0.83 ) }, diff --git a/common/settings/color_settings.cpp b/common/settings/color_settings.cpp index 31c98808ed..4d24df43be 100644 --- a/common/settings/color_settings.cpp +++ b/common/settings/color_settings.cpp @@ -203,7 +203,7 @@ COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath ) CLR( "3d_viewer.background_bottom", LAYER_3D_BACKGROUND_BOTTOM ); CLR( "3d_viewer.background_top", LAYER_3D_BACKGROUND_TOP ); CLR( "3d_viewer.board", LAYER_3D_BOARD ); - CLR( "3d_viewer.copper", LAYER_3D_COPPER ); + CLR( "3d_viewer.copper", LAYER_3D_COPPER_TOP ); CLR( "3d_viewer.silkscreen_bottom", LAYER_3D_SILKSCREEN_BOTTOM ); CLR( "3d_viewer.silkscreen_top", LAYER_3D_SILKSCREEN_TOP ); CLR( "3d_viewer.soldermask_bottom", LAYER_3D_SOLDERMASK_BOTTOM ); diff --git a/common/widgets/bitmap_toggle.cpp b/common/widgets/bitmap_toggle.cpp index 23d8066f3f..8f6519b739 100644 --- a/common/widgets/bitmap_toggle.cpp +++ b/common/widgets/bitmap_toggle.cpp @@ -53,7 +53,7 @@ BITMAP_TOGGLE::BITMAP_TOGGLE( wxWindow *aParent, wxWindowID aId, const wxBitmap& { wxLongLong now = wxGetLocalTimeMillis(); - if( now - m_debounce < 50 ) + if( now - m_debounce < 200 ) return; else m_debounce = now; diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h index 3caabf637f..19e0f152a7 100644 --- a/include/eda_base_frame.h +++ b/include/eda_base_frame.h @@ -80,6 +80,7 @@ class FILE_HISTORY; class SETTINGS_MANAGER; class SEARCH_STACK; class APP_SETTINGS_BASE; +class APPEARANCE_CONTROLS_3D; struct WINDOW_SETTINGS; struct WINDOW_STATE; @@ -738,33 +739,31 @@ private: wxPoint m_normalFramePos; wxSize m_normalFrameSize; - wxString m_aboutTitle; // Name of program displayed in About. + wxString m_aboutTitle; // Name of program displayed in About. - wxAuiManager m_auimgr; - wxString m_perspective; // wxAuiManager perspective. + wxAuiManager m_auimgr; + wxString m_perspective; // wxAuiManager perspective. + WX_INFOBAR* m_infoBar; // Infobar for the frame + APPEARANCE_CONTROLS_3D* m_appearancePanel; + wxString m_configName; // Prefix used to identify some params (frame + // size) and to name some config files (legacy + // hotkey files) + SETTINGS_MANAGER* m_settingsManager; - WX_INFOBAR* m_infoBar; // Infobar for the frame + FILE_HISTORY* m_fileHistory; // The frame's recently opened file list + bool m_supportsAutoSave; + bool m_autoSavePending; + bool m_autoSaveRequired; + wxTimer* m_autoSaveTimer; - wxString m_configName; // Prefix used to identify some params (frame size...) - // and to name some config files (legacy hotkey files) + int m_undoRedoCountMax; // undo/Redo command Max depth - SETTINGS_MANAGER* m_settingsManager; + UNDO_REDO_CONTAINER m_undoList; // Objects list for the undo command (old data) + UNDO_REDO_CONTAINER m_redoList; // Objects list for the redo command (old data) - FILE_HISTORY* m_fileHistory; // The frame's recently opened file list + wxString m_mruPath; // Most recently used path. - bool m_supportsAutoSave; - bool m_autoSavePending; - bool m_autoSaveRequired; - wxTimer* m_autoSaveTimer; - - int m_undoRedoCountMax; // undo/Redo command Max depth - - UNDO_REDO_CONTAINER m_undoList; // Objects list for the undo command (old data) - UNDO_REDO_CONTAINER m_redoList; // Objects list for the redo command (old data) - - wxString m_mruPath; // Most recently used path. - - ORIGIN_TRANSFORMS m_originTransforms; // Default display origin transforms object. + ORIGIN_TRANSFORMS m_originTransforms; // Default display origin transforms object. ///< Map containing the UI update handlers registered with wx for each action. std::map m_uiUpdateMap; diff --git a/include/layer_ids.h b/include/layer_ids.h index 2ec5d2dca6..b7fa91f707 100644 --- a/include/layer_ids.h +++ b/include/layer_ids.h @@ -442,14 +442,27 @@ enum LAYER_3D_ID : int LAYER_3D_BACKGROUND_BOTTOM, LAYER_3D_BACKGROUND_TOP, LAYER_3D_BOARD, - LAYER_3D_COPPER, + LAYER_3D_COPPER_TOP, + LAYER_3D_COPPER_BOTTOM, LAYER_3D_SILKSCREEN_BOTTOM, LAYER_3D_SILKSCREEN_TOP, LAYER_3D_SOLDERMASK_BOTTOM, LAYER_3D_SOLDERMASK_TOP, LAYER_3D_SOLDERPASTE, + LAYER_3D_ADHESIVE, + LAYER_3D_USER_COMMENTS, + LAYER_3D_USER_DRAWINGS, + LAYER_3D_USER_ECO1, + LAYER_3D_USER_ECO2, + LAYER_3D_TH_MODELS, + LAYER_3D_SMD_MODELS, + LAYER_3D_VIRTUAL_MODELS, + LAYER_3D_MODELS_NOT_IN_POS, + LAYER_3D_MODELS_MARKED_DNP, + LAYER_3D_AXES, + LAYER_3D_BOUNDING_BOXES, - LAYER_3D_END = LAYER_3D_SOLDERPASTE + LAYER_3D_END }; /// Must update this if you add any enums after GerbView! diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp index 54c2ddbc36..ab9b3e26a5 100644 --- a/pcbnew/pcb_base_edit_frame.cpp +++ b/pcbnew/pcb_base_edit_frame.cpp @@ -26,6 +26,7 @@ #include #include #include +#include <3d_viewer/eda_3d_viewer_frame.h> #include #include #include @@ -285,6 +286,11 @@ void PCB_BASE_EDIT_FRAME::handleActivateEvent( wxActivateEvent& aEvent ) void PCB_BASE_EDIT_FRAME::onDarkModeToggle() { m_appearancePanel->OnDarkModeToggle(); + + EDA_3D_VIEWER_FRAME* viewer = Get3DViewerFrame(); + + if( viewer ) + viewer->OnDarkModeToggle(); } diff --git a/pcbnew/widgets/appearance_controls.cpp b/pcbnew/widgets/appearance_controls.cpp index 2013d447c8..63a2d7556e 100644 --- a/pcbnew/widgets/appearance_controls.cpp +++ b/pcbnew/widgets/appearance_controls.cpp @@ -1251,6 +1251,8 @@ void APPEARANCE_CONTROLS::SetObjectVisible( GAL_LAYER_ID aLayer, bool isVisible m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible ); + m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh ); + m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible ); m_frame->GetCanvas()->Refresh(); } @@ -1279,6 +1281,8 @@ void APPEARANCE_CONTROLS::setVisibleLayers( LSET aLayers ) // might be the last layer the item is visible on). return dynamic_cast( aItem ) || dynamic_cast( aItem ); } ); + + m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh ); } } @@ -1299,6 +1303,8 @@ void APPEARANCE_CONTROLS::setVisibleObjects( GAL_SET aLayers ) aLayers.set( LAYER_RATSNEST, m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest ); m_frame->GetBoard()->SetVisibleElements( aLayers ); + + m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh ); } } @@ -2223,31 +2229,29 @@ void APPEARANCE_CONTROLS::rebuildObjects() if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) ) continue; - if( !s_setting.spacer ) + m_objectSettings.emplace_back( std::make_unique( s_setting ) ); + + std::unique_ptr& setting = m_objectSettings.back(); + + // Because s_render_rows is created static, we must explicitly call wxGetTranslation + // for texts which are internationalized (tool tips and item names) + setting->tooltip = wxGetTranslation( s_setting.tooltip ); + setting->label = wxGetTranslation( s_setting.label ); + + if( setting->can_control_opacity ) { - m_objectSettings.emplace_back( std::make_unique( s_setting ) ); - - std::unique_ptr& setting = m_objectSettings.back(); - - // Because s_render_rows is created static, we must explicitly call wxGetTranslation - // for texts which are internationalized (tool tips and item names) - setting->tooltip = wxGetTranslation( s_setting.tooltip ); - setting->label = wxGetTranslation( s_setting.label ); - - if( setting->can_control_opacity ) - { - int width = m_windowObjects->GetTextExtent( setting->label ).x + 5; - labelWidth = std::max( labelWidth, width ); - } - - m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get(); + int width = m_windowObjects->GetTextExtent( setting->label ).x + 5; + labelWidth = std::max( labelWidth, width ); } + + if( !s_setting.spacer ) + m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get(); } for( const std::unique_ptr& setting : m_objectSettings ) { if( setting->spacer ) - m_objectsOuterSizer->AddSpacer( m_pointSize ); + m_objectsOuterSizer->AddSpacer( m_pointSize / 2 ); else appendObject( setting ); }