diff --git a/3d-viewer/3d_viewer/3d_toolbar.cpp b/3d-viewer/3d_viewer/3d_toolbar.cpp index b34a1ebc26..4ab089bc69 100644 --- a/3d-viewer/3d_viewer/3d_toolbar.cpp +++ b/3d-viewer/3d_viewer/3d_toolbar.cpp @@ -4,7 +4,7 @@ * 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) 1992-2022 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 @@ -25,6 +25,7 @@ */ #include +#include #include #include @@ -50,6 +51,21 @@ void EDA_3D_VIEWER_FRAME::ReCreateMainToolbar() m_mainToolBar->SetAuiManager( &m_auimgr ); } + m_viewportsLabel = new wxStaticText( this, wxID_ANY, _( "Viewports (Alt+Tab):" ) ); + m_viewportsLabel->Wrap( -1 ); + + m_cbViewports = new wxChoice( this, 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->SetSelection( m_cbViewports->GetCount() - 3 ); + m_lastSelectedViewport = nullptr; + // Set up toolbar m_mainToolBar->AddTool( ID_RELOAD3D_BOARD, wxEmptyString, KiScaledBitmap( BITMAPS::import3d, this ), _( "Reload board" ) ); @@ -99,5 +115,11 @@ void EDA_3D_VIEWER_FRAME::ReCreateMainToolbar() m_mainToolBar->Add( EDA_3D_ACTIONS::showSMD, ACTION_TOOLBAR::TOGGLE ); m_mainToolBar->Add( EDA_3D_ACTIONS::showVirtual, ACTION_TOOLBAR::TOGGLE ); + m_mainToolBar->AddScaledSeparator( this ); + m_mainToolBar->AddControl( m_viewportsLabel ); + m_mainToolBar->AddControl( m_cbViewports ); + 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 2afa0078f4..9898082100 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp +++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp @@ -28,7 +28,12 @@ #include #include #include +#include +#include #include "eda_3d_viewer_frame.h" +#include "eda_list_dialog.h" +#include "wx/generic/textdlgg.h" +#include #include #include <3d_viewer_id.h> #include <3d_viewer/tools/eda_3d_actions.h> @@ -40,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -73,8 +79,8 @@ BEGIN_EVENT_TABLE( EDA_3D_VIEWER_FRAME, EDA_BASE_FRAME ) EDA_3D_VIEWER_FRAME::Process_Special_Functions ) EVT_MENU( wxID_CLOSE, EDA_3D_VIEWER_FRAME::Exit3DFrame ) - EVT_MENU( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER_FRAME::OnRenderEngineSelection ) - EVT_MENU( ID_DISABLE_RAY_TRACING, EDA_3D_VIEWER_FRAME::OnDisableRayTracing ) + EVT_MENU( ID_RENDER_CURRENT_VIEW, EDA_3D_VIEWER_FRAME::onRenderEngineSelection ) + EVT_MENU( ID_DISABLE_RAY_TRACING, EDA_3D_VIEWER_FRAME::onDisableRayTracing ) EVT_CLOSE( EDA_3D_VIEWER_FRAME::OnCloseWindow ) END_EVENT_TABLE() @@ -85,6 +91,8 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle, wxDefaultPosition, wxDefaultSize, style, QUALIFIED_VIEWER3D_FRAMENAME( aParent ) ), 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 ) { wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME %s" ), aTitle ); @@ -113,6 +121,8 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent LoadSettings( cfg ); loadCommonSettings(); + SetUserViewports( Prj().GetProjectFile().m_Viewports3D ); + // Create the manager m_toolManager = new TOOL_MANAGER; m_toolManager->SetEnvironment( GetBoard(), nullptr, nullptr, cfg, this ); @@ -171,6 +181,13 @@ 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 ); } @@ -183,6 +200,15 @@ EDA_3D_VIEWER_FRAME::~EDA_3D_VIEWER_FRAME() } #endif + 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 ); + m_canvas->SetEventDispatcher( nullptr ); m_auimgr.UnInit(); @@ -255,6 +281,45 @@ void EDA_3D_VIEWER_FRAME::setupUIConditions() } +bool EDA_3D_VIEWER_FRAME::TryBefore( wxEvent& aEvent ) +{ + static bool s_viewportSwitcherShown = false; + +#ifdef __WXMAC__ + wxKeyCode viewSwitchKey = WXK_ALT; +#else + wxKeyCode viewSwitchKey = WXK_WINDOWS_LEFT; +#endif + + if( aEvent.GetEventType() != wxEVT_CHAR && aEvent.GetEventType() != wxEVT_CHAR_HOOK ) + return wxFrame::TryBefore( aEvent ); + + if( !s_viewportSwitcherShown && wxGetKeyState( viewSwitchKey ) && wxGetKeyState( WXK_TAB ) ) + { + if( this->IsActive() ) + { + if( m_viewportMRU.size() > 0 ) + { + EDA_VIEW_SWITCHER switcher( this, m_viewportMRU, viewSwitchKey ); + + s_viewportSwitcherShown = true; + switcher.ShowModal(); + s_viewportSwitcherShown = false; + + int idx = switcher.GetSelection(); + + if( idx >= 0 && idx < (int) m_viewportMRU.size() ) + applyViewport( m_viewportMRU[idx] ); + + return true; + } + } + } + + return wxFrame::TryBefore( aEvent ); +} + + void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent ) { KIWAY_PLAYER::handleIconizeEvent( aEvent ); @@ -369,27 +434,192 @@ void EDA_3D_VIEWER_FRAME::Process_Special_Functions( wxCommandEvent &event ) } -void EDA_3D_VIEWER_FRAME::OnRenderEngineSelection( wxCommandEvent &event ) +std::vector EDA_3D_VIEWER_FRAME::GetUserViewports() const { - RENDER_ENGINE old_engine = m_boardAdapter.m_Cfg->m_Render.engine; + 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 && m_cbViewports->GetSelection() != idx ) + { + 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(); + } + 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 ) + { + VIEWPORT3D* viewport = static_cast( m_cbViewports->GetClientData( index ) ); + + wxCHECK( viewport, /* void */ ); + + applyViewport( viewport->name ); + + 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( -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_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; + RENDER_ENGINE old_engine = engine; if( old_engine == RENDER_ENGINE::OPENGL ) - m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::RAYTRACING; + engine = RENDER_ENGINE::RAYTRACING; else - m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL; + engine = RENDER_ENGINE::OPENGL; wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ), - m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::RAYTRACING ? - wxT( "raytracing" ) - : - wxT( "realtime" ) ); + engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) ); - if( old_engine != m_boardAdapter.m_Cfg->m_Render.engine ) + if( old_engine != engine ) RenderEngineChanged(); } -void EDA_3D_VIEWER_FRAME::OnDisableRayTracing( wxCommandEvent& aEvent ) +void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent ) { wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ), __WXFUNCTION__ ); @@ -435,6 +665,13 @@ 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 ); diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_frame.h b/3d-viewer/3d_viewer/eda_3d_viewer_frame.h index a3dbe5cef8..9b85ad2884 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.h +++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.h @@ -4,7 +4,7 @@ * 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-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2022 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 @@ -106,6 +106,9 @@ 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; @@ -122,22 +125,26 @@ protected: void handleIconizeEvent( wxIconizeEvent& aEvent ) override; + void applyViewport( const wxString& aViewportName ); + private: /// Called when user press the File->Exit void Exit3DFrame( wxCommandEvent& event ); void OnCloseWindow( wxCloseEvent& event ); + bool TryBefore( wxEvent& aEvent ) override; + void Process_Special_Functions( wxCommandEvent& event ); - void OnRenderEngineSelection( wxCommandEvent& event ); - void OnDisableRayTracing( wxCommandEvent& aEvent ); + 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 Install3DViewOptionDialog( wxCommandEvent& event ); + void passOnFocus(); void CreateMenuBar(); void ReCreateMainToolbar(); @@ -162,17 +169,24 @@ private: */ void loadCommonSettings(); - wxFileName m_defaultSaveScreenshotFileName; +private: + wxFileName m_defaultSaveScreenshotFileName; - ACTION_TOOLBAR* m_mainToolBar; - EDA_3D_CANVAS* m_canvas; - BOARD_ADAPTER m_boardAdapter; - CAMERA& m_currentCamera; - TRACK_BALL m_trackBallCamera; + 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_disable_ray_tracing; - NL_3D_VIEWER_PLUGIN* m_spaceMouse; + 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. diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_settings.h b/3d-viewer/3d_viewer/eda_3d_viewer_settings.h index 2a1a3fdc7b..0c9b9a2af2 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer_settings.h +++ b/3d-viewer/3d_viewer/eda_3d_viewer_settings.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jon Evans - * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2022 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,7 +26,7 @@ #include #include #include - +#include "render_settings.h" class EDA_3D_VIEWER_SETTINGS : public APP_SETTINGS_BASE { diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index 87bfde723f..7b1e9ab77e 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -11,6 +11,7 @@ include_directories( 3d_viewer ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include/gal/opengl + ${CMAKE_SOURCE_DIR}/common/dialogs ${INC_AFTER} ) diff --git a/common/project/board_project_settings.cpp b/common/project/board_project_settings.cpp index 059cd96fbd..09e2add95a 100644 --- a/common/project/board_project_settings.cpp +++ b/common/project/board_project_settings.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jon Evans - * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2022 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 @@ -187,6 +187,118 @@ void PARAM_VIEWPORT::jsonToViewports( const nlohmann::json& aJson ) if( viewport.contains( "h" ) ) v.rect.SetHeight( viewport.at( "h" ).get() ); + m_viewports->emplace_back( v ); + } + } +} + + +PARAM_VIEWPORT3D::PARAM_VIEWPORT3D( const std::string& aPath, + std::vector* aViewportList ) : + PARAM_LAMBDA( aPath, + std::bind( &PARAM_VIEWPORT3D::viewportsToJson, this ), + std::bind( &PARAM_VIEWPORT3D::jsonToViewports, this, _1 ), + {} ), + m_viewports( aViewportList ) +{ + wxASSERT( aViewportList ); +} + + +nlohmann::json PARAM_VIEWPORT3D::viewportsToJson() +{ + nlohmann::json ret = nlohmann::json::array(); + + for( const VIEWPORT3D& viewport : *m_viewports ) + { + nlohmann::json js = { + { "name", viewport.name }, + { "xx", viewport.matrix[0].x }, + { "xy", viewport.matrix[0].y }, + { "xz", viewport.matrix[0].z }, + { "xw", viewport.matrix[0].w }, + { "yx", viewport.matrix[1].x }, + { "yy", viewport.matrix[1].y }, + { "yz", viewport.matrix[1].z }, + { "yw", viewport.matrix[1].w }, + { "zx", viewport.matrix[2].x }, + { "zy", viewport.matrix[2].y }, + { "zz", viewport.matrix[2].z }, + { "zw", viewport.matrix[2].w }, + { "wx", viewport.matrix[3].x }, + { "wy", viewport.matrix[3].y }, + { "wz", viewport.matrix[3].z }, + { "ww", viewport.matrix[3].w } + }; + + ret.push_back( js ); + } + + return ret; +} + + +void PARAM_VIEWPORT3D::jsonToViewports( const nlohmann::json& aJson ) +{ + if( aJson.empty() || !aJson.is_array() ) + return; + + m_viewports->clear(); + + for( const nlohmann::json& viewport : aJson ) + { + if( viewport.contains( "name" ) ) + { + VIEWPORT3D v( viewport.at( "name" ).get() ); + + if( viewport.contains( "xx" ) ) + v.matrix[0].x = viewport.at( "xx" ).get(); + + if( viewport.contains( "xy" ) ) + v.matrix[0].y = viewport.at( "xy" ).get(); + + if( viewport.contains( "xz" ) ) + v.matrix[0].z = viewport.at( "xz" ).get(); + + if( viewport.contains( "xw" ) ) + v.matrix[0].w = viewport.at( "xw" ).get(); + + if( viewport.contains( "yx" ) ) + v.matrix[1].x = viewport.at( "yx" ).get(); + + if( viewport.contains( "yy" ) ) + v.matrix[1].y = viewport.at( "yy" ).get(); + + if( viewport.contains( "yz" ) ) + v.matrix[1].z = viewport.at( "yz" ).get(); + + if( viewport.contains( "yw" ) ) + v.matrix[1].w = viewport.at( "yw" ).get(); + + if( viewport.contains( "zx" ) ) + v.matrix[2].x = viewport.at( "zx" ).get(); + + if( viewport.contains( "zy" ) ) + v.matrix[2].y = viewport.at( "zy" ).get(); + + if( viewport.contains( "zz" ) ) + v.matrix[2].z = viewport.at( "zz" ).get(); + + if( viewport.contains( "zw" ) ) + v.matrix[2].w = viewport.at( "zw" ).get(); + + if( viewport.contains( "wx" ) ) + v.matrix[3].x = viewport.at( "wx" ).get(); + + if( viewport.contains( "wy" ) ) + v.matrix[3].y = viewport.at( "wy" ).get(); + + if( viewport.contains( "wz" ) ) + v.matrix[3].z = viewport.at( "wz" ).get(); + + if( viewport.contains( "ww" ) ) + v.matrix[3].w = viewport.at( "ww" ).get(); + m_viewports->emplace_back( v ); } } diff --git a/common/project/project_file.cpp b/common/project/project_file.cpp index 2704402c00..13a2fe0797 100644 --- a/common/project/project_file.cpp +++ b/common/project/project_file.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 CERN - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. * @author Jon Evans * * This program is free software: you can redistribute it and/or modify it @@ -111,6 +111,8 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) : m_params.emplace_back( new PARAM_LAYER_PRESET( "board.layer_presets", &m_LayerPresets ) ); m_params.emplace_back( new PARAM_VIEWPORT( "board.viewports", &m_Viewports ) ); + + m_params.emplace_back( new PARAM_VIEWPORT3D( "board.3dviewports", &m_Viewports3D ) ); } diff --git a/include/project/board_project_settings.h b/include/project/board_project_settings.h index 3a64cb501a..4fdd8e0dc1 100644 --- a/include/project/board_project_settings.h +++ b/include/project/board_project_settings.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jon Evans - * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2022 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 @@ -27,6 +27,7 @@ // Can be removed by refactoring PARAM_LAYER_PRESET #include #include +#include /** * This file contains data structures that are saved in the project file or project local settings @@ -212,4 +213,35 @@ private: std::vector* m_viewports; }; + +struct VIEWPORT3D +{ + VIEWPORT3D( const wxString& aName = wxEmptyString ) : + name( aName ) + { } + + VIEWPORT3D( const wxString& aName, glm::mat4 aViewMatrix ) : + name( aName ), + matrix( aViewMatrix ) + { } + + wxString name; + glm::mat4 matrix; +}; + + +class PARAM_VIEWPORT3D : public PARAM_LAMBDA +{ +public: + PARAM_VIEWPORT3D( const std::string& aPath, std::vector* aViewportList ); + +private: + nlohmann::json viewportsToJson(); + + void jsonToViewports( const nlohmann::json & aJson ); + + std::vector* m_viewports; +}; + + #endif // KICAD_BOARD_PROJECT_SETTINGS_H diff --git a/include/project/project_file.h b/include/project/project_file.h index 0204e7d9fa..9269ec14e9 100644 --- a/include/project/project_file.h +++ b/include/project/project_file.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 CERN - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. * @author Jon Evans * * This program is free software: you can redistribute it and/or modify it @@ -170,6 +170,7 @@ public: std::vector m_LayerPresets; /// List of stored layer presets std::vector m_Viewports; /// List of stored viewports (pos + zoom) + std::vector m_Viewports3D; /// List of stored 3D viewports (view matrixes) private: /// An list of schematic sheets in this project diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp index 69b03c7920..f09ce2feb6 100644 --- a/pcbnew/pcb_base_edit_frame.cpp +++ b/pcbnew/pcb_base_edit_frame.cpp @@ -113,7 +113,7 @@ bool PCB_BASE_EDIT_FRAME::TryBefore( wxEvent& aEvent ) { const wxArrayString& mru = m_appearancePanel->GetLayerPresetsMRU(); - if( mru.size() > 1 ) + if( mru.size() > 0 ) { EDA_VIEW_SWITCHER switcher( this, mru, presetSwitchKey ); @@ -136,7 +136,7 @@ bool PCB_BASE_EDIT_FRAME::TryBefore( wxEvent& aEvent ) { const wxArrayString& mru = m_appearancePanel->GetViewportsMRU(); - if( mru.size() > 1 ) + if( mru.size() > 0 ) { EDA_VIEW_SWITCHER switcher( this, mru, viewSwitchKey ); diff --git a/pcbnew/widgets/appearance_controls.cpp b/pcbnew/widgets/appearance_controls.cpp index 66a02eadce..5743d19081 100644 --- a/pcbnew/widgets/appearance_controls.cpp +++ b/pcbnew/widgets/appearance_controls.cpp @@ -2720,7 +2720,7 @@ void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent ) } else if( index == count - 1 ) { - // Delete an existing preset + // Delete an existing viewport wxArrayString headers; std::vector items; @@ -2743,7 +2743,7 @@ void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent ) if( idx != wxNOT_FOUND ) { - m_layerPresets.erase( viewportName ); + m_viewports.erase( viewportName ); m_cbViewports->Delete( idx ); m_viewportMRU.Remove( viewportName ); }