diff --git a/3d-viewer/3d_viewer/3d_menubar.cpp b/3d-viewer/3d_viewer/3d_menubar.cpp
index 4219dbbd4a..186c7e2c4e 100644
--- a/3d-viewer/3d_viewer/3d_menubar.cpp
+++ b/3d-viewer/3d_viewer/3d_menubar.cpp
@@ -48,15 +48,8 @@ void EDA_3D_VIEWER_FRAME::doReCreateMenuBar()
     //
     ACTION_MENU* fileMenu = new ACTION_MENU( false, tool );
 
-    fileMenu->Add( _( "Export Current View as PNG..." ),
-                   wxEmptyString,
-                   ID_MENU_SCREENCOPY_PNG,
-                   BITMAPS::export_png );
-
-    fileMenu->Add( _( "Export Current View as JPEG..." ),
-                   wxEmptyString,
-                   ID_MENU_SCREENCOPY_JPEG,
-                   BITMAPS::export_file );
+    fileMenu->Add( EDA_3D_ACTIONS::exportAsPNG );
+    fileMenu->Add( EDA_3D_ACTIONS::exportAsJPEG );
 
     fileMenu->AppendSeparator();
     fileMenu->AddClose( _( "3D Viewer" ) );
@@ -67,10 +60,7 @@ void EDA_3D_VIEWER_FRAME::doReCreateMenuBar()
     // The translated modifiers do not always work
     ACTION_MENU* editMenu = new ACTION_MENU( false, tool );
 
-    editMenu->Add( _( "Copy 3D Image" ),
-                   wxEmptyString,
-                   ID_TOOL_SCREENCOPY_TOCLIBBOARD,
-                   BITMAPS::copy );
+    editMenu->Add( EDA_3D_ACTIONS::copyToClipboard );
 
 
     //-- View menu -------------------------------------------------------
@@ -122,10 +112,7 @@ void EDA_3D_VIEWER_FRAME::doReCreateMenuBar()
     //
     ACTION_MENU* prefsMenu = new ACTION_MENU( false, tool );
 
-    prefsMenu->Add( _( "Raytracing" ), "",
-                    ID_RENDER_CURRENT_VIEW,
-                    BITMAPS::tools,
-                    ACTION_MENU::CHECK );
+    prefsMenu->Add( EDA_3D_ACTIONS::toggleRaytacing, ACTION_MENU::CHECK );
 
     prefsMenu->Add( ACTIONS::openPreferences );
 
diff --git a/3d-viewer/3d_viewer/3d_toolbar.cpp b/3d-viewer/3d_viewer/3d_toolbar.cpp
index 51d4e70a71..72523c6d4e 100644
--- a/3d-viewer/3d_viewer/3d_toolbar.cpp
+++ b/3d-viewer/3d_viewer/3d_toolbar.cpp
@@ -40,26 +40,13 @@ std::optional<TOOLBAR_CONFIGURATION> EDA_3D_VIEWER_FRAME::DefaultTopMainToolbarC
     TOOLBAR_CONFIGURATION config;
 
     // clang-format off
-    // Set up toolbar
-    /* TODO (ISM): Move to action
-    m_tbTopMain->AddTool( ID_RELOAD3D_BOARD, wxEmptyString,
-        KiBitmapBundle( BITMAPS::import3d ),
-        _( "Reload board" ) );
-    */
+    config.AppendAction( EDA_3D_ACTIONS::reloadBoard );
 
-    config.AppendSeparator();
-    /* TODO (ISM): Move to action
-    m_tbTopMain->AddTool( ID_TOOL_SCREENCOPY_TOCLIBBOARD, wxEmptyString,
-        KiBitmapBundle( BITMAPS::copy ),
-        _( "Copy 3D image to clipboard" ) );
-*/
+    config.AppendSeparator()
+          .AppendAction( EDA_3D_ACTIONS::copyToClipboard );
 
-    config.AppendSeparator();
-    /* TODO (ISM): Move to action
-    m_tbTopMain->AddTool( ID_RENDER_CURRENT_VIEW, wxEmptyString,
-        KiBitmapBundle( BITMAPS::ray_tracing ),
-        _( "Render current view using Raytracing" ), wxITEM_CHECK );
-*/
+    config.AppendSeparator()
+          .AppendAction( EDA_3D_ACTIONS::toggleRaytacing );
 
     config.AppendSeparator()
           .AppendAction( ACTIONS::zoomRedraw )
diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp
index 6933364530..386e27720a 100644
--- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp
+++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp
@@ -80,7 +80,6 @@ BEGIN_EVENT_TABLE( EDA_3D_VIEWER_FRAME, KIWAY_PLAYER )
                     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_CLOSE( EDA_3D_VIEWER_FRAME::OnCloseWindow )
@@ -272,7 +271,7 @@ void EDA_3D_VIEWER_FRAME::setupUIConditions()
                 return m_boardAdapter.m_Cfg->m_AuiPanels.show_layer_manager;
             };
 
-    RegisterUIUpdateHandler( ID_RENDER_CURRENT_VIEW, ACTION_CONDITIONS().Check( raytracing ) );
+    mgr->SetConditions( EDA_3D_ACTIONS::toggleRaytacing, ACTION_CONDITIONS().Check( raytracing ) );
 
     mgr->SetConditions( EDA_3D_ACTIONS::showTHT, ACTION_CONDITIONS().Check( showTH ) );
     mgr->SetConditions( EDA_3D_ACTIONS::showSMD, ACTION_CONDITIONS().Check( showSMD ) );
@@ -467,16 +466,6 @@ void EDA_3D_VIEWER_FRAME::Process_Special_Functions( wxCommandEvent &event )
 
     switch( id )
     {
-    case ID_RELOAD3D_BOARD:
-        NewDisplay( true );
-        break;
-
-    case ID_TOOL_SCREENCOPY_TOCLIBBOARD:
-    case ID_MENU_SCREENCOPY_PNG:
-    case ID_MENU_SCREENCOPY_JPEG:
-        takeScreenshot( event );
-        return;
-
     case ID_MENU3D_RESET_DEFAULTS:
     {
         SETTINGS_MANAGER&       mgr = Pgm().GetSettingsManager();
@@ -499,24 +488,6 @@ void EDA_3D_VIEWER_FRAME::Process_Special_Functions( wxCommandEvent &event )
 }
 
 
-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 )
-        engine = RENDER_ENGINE::RAYTRACING;
-    else
-        engine = RENDER_ENGINE::OPENGL;
-
-    wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::OnRenderEngineSelection type %s " ),
-                engine == RENDER_ENGINE::RAYTRACING ? wxT( "raytracing" ) : wxT( "realtime" ) );
-
-    if( old_engine != engine )
-        RenderEngineChanged();
-}
-
-
 void EDA_3D_VIEWER_FRAME::onDisableRayTracing( wxCommandEvent& aEvent )
 {
     wxLogTrace( m_logTrace, wxT( "EDA_3D_VIEWER_FRAME::%s disabling ray tracing." ),
@@ -701,15 +672,15 @@ void EDA_3D_VIEWER_FRAME::OnDarkModeToggle()
 }
 
 
-void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
+void EDA_3D_VIEWER_FRAME::TakeScreenshot( EDA_3D_VIEWER_EXPORT_FORMAT aFormat )
 {
     wxString   fullFileName;
     bool       fmt_is_jpeg = false;
 
-    if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
+    if( aFormat == EDA_3D_VIEWER_EXPORT_FORMAT::JPEG )
         fmt_is_jpeg = true;
 
-    if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
+    if( aFormat != EDA_3D_VIEWER_EXPORT_FORMAT::CLIPBOARD )
     {
         // Remember path between saves during this session only.
         const wxString wildcard =
@@ -773,7 +744,7 @@ void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
 
     cfg.highlight_on_rollover = allow_highlight;
 
-    if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
+    if( aFormat == EDA_3D_VIEWER_EXPORT_FORMAT::CLIPBOARD )
     {
         wxBitmap bitmap( screenshotImage );
 
diff --git a/3d-viewer/3d_viewer/eda_3d_viewer_frame.h b/3d-viewer/3d_viewer/eda_3d_viewer_frame.h
index 33ce0dd401..004ab0f088 100644
--- a/3d-viewer/3d_viewer/eda_3d_viewer_frame.h
+++ b/3d-viewer/3d_viewer/eda_3d_viewer_frame.h
@@ -57,6 +57,13 @@ enum EDA_3D_VIEWER_STATUSBAR
     ZOOM_LEVEL,
 };
 
+enum class EDA_3D_VIEWER_EXPORT_FORMAT
+{
+    CLIPBOARD,
+    PNG,
+    JPEG
+};
+
 /**
  * Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard
  */
@@ -125,6 +132,12 @@ public:
 
     std::optional<TOOLBAR_CONFIGURATION> DefaultTopMainToolbarConfig() override;
 
+    /**
+     *  Create a Screenshot of the current 3D view.
+     *  Output file format is png or jpeg, or image is copied to the clipboard
+     */
+    void TakeScreenshot( EDA_3D_VIEWER_EXPORT_FORMAT aFormat );
+
 protected:
     void setupUIConditions() override;
 
@@ -140,7 +153,6 @@ private:
 
     void Process_Special_Functions( wxCommandEvent& event );
 
-    void onRenderEngineSelection( wxCommandEvent& event );
     void onDisableRayTracing( wxCommandEvent& aEvent );
 
     void OnActivate( wxActivateEvent& event );
@@ -148,12 +160,6 @@ private:
 
     void doReCreateMenuBar() override;
 
-    /**
-     *  Create a Screenshot of the current 3D view.
-     *  Output file format is png or jpeg, or image is copied to the clipboard
-     */
-    void takeScreenshot( wxCommandEvent& event );
-
     /**
      * @brief RenderEngineChanged - Update toolbar icon and call canvas RenderEngineChanged
      */
diff --git a/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp b/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp
index 3f75e25bec..c90dc7d789 100644
--- a/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp
+++ b/3d-viewer/3d_viewer/tools/eda_3d_actions.cpp
@@ -23,6 +23,7 @@
 #include <bitmaps.h>
 #include <3d_viewer_id.h>
 #include <3d_enums.h>
+#include <3d-viewer/3d_viewer/eda_3d_viewer_frame.h>
 #include "eda_3d_actions.h"
 #include "tool/tool_action.h"
 
@@ -38,7 +39,47 @@
 TOOL_ACTION EDA_3D_ACTIONS::controlActivate( TOOL_ACTION_ARGS()
         .Name( "3DViewer.Control" )
         .Scope( AS_GLOBAL )
-        .Flags( AF_ACTIVATE ) );
+        .Flags( AF_ACTIVATE )
+        .ToolbarState( TOOLBAR_STATE::HIDDEN) );
+
+TOOL_ACTION EDA_3D_ACTIONS:: reloadBoard( TOOL_ACTION_ARGS()
+        .Name( "3DViewer.Control.reloadBoard" )
+        .Scope( AS_GLOBAL )
+        .FriendlyName( _( "Reload board" ) )
+        .Tooltip( _( "Reload board and refresh 3D view" ) )
+        .Icon( BITMAPS::import3d ) );
+
+TOOL_ACTION EDA_3D_ACTIONS::toggleRaytacing( TOOL_ACTION_ARGS()
+        .Name( "3DViewer.Control.toggleRaytacing" )
+        .Scope( AS_GLOBAL )
+        .FriendlyName( _( "Use raytracing" ) )
+        .Tooltip( _( "Render current view using Raytracing" ) )
+        .Icon( BITMAPS::ray_tracing )
+        .ToolbarState( TOOLBAR_STATE::TOGGLE) );
+
+TOOL_ACTION EDA_3D_ACTIONS::copyToClipboard( TOOL_ACTION_ARGS()
+        .Name( "3DViewer.Control.copyToClipboard" )
+        .Scope( AS_GLOBAL )
+        .FriendlyName( _( "Copy 3D image to clipboard" ) )
+        .Tooltip( _( "Copy the current 3D image to the clipboard" ) )
+        .Icon( BITMAPS::copy )
+        .Parameter<EDA_3D_VIEWER_EXPORT_FORMAT>( EDA_3D_VIEWER_EXPORT_FORMAT::CLIPBOARD ) );
+
+TOOL_ACTION EDA_3D_ACTIONS::exportAsPNG( TOOL_ACTION_ARGS()
+        .Name( "3DViewer.Control.exportAsPNG" )
+        .Scope( AS_GLOBAL )
+        .FriendlyName( _( "Export Current View as PNG..." ) )
+        .Tooltip( _( "Export the Current View as a PNG image" ) )
+        .Icon( BITMAPS::export_png )
+        .Parameter<EDA_3D_VIEWER_EXPORT_FORMAT>( EDA_3D_VIEWER_EXPORT_FORMAT::PNG ) );
+
+TOOL_ACTION EDA_3D_ACTIONS::exportAsJPEG( TOOL_ACTION_ARGS()
+        .Name( "3DViewer.Control.exportAsJPEG" )
+        .Scope( AS_GLOBAL )
+        .FriendlyName( _( "Export Current View as JPEG..." ) )
+        .Tooltip( _( "Export the Current View as a JPEG image" ) )
+        .Icon( BITMAPS::export_file )
+        .Parameter<EDA_3D_VIEWER_EXPORT_FORMAT>( EDA_3D_VIEWER_EXPORT_FORMAT::JPEG ) );
 
 TOOL_ACTION EDA_3D_ACTIONS::pivotCenter( TOOL_ACTION_ARGS()
         .Name( "3DViewer.Control.pivotCenter" )
diff --git a/3d-viewer/3d_viewer/tools/eda_3d_actions.h b/3d-viewer/3d_viewer/tools/eda_3d_actions.h
index 4344c43f59..ee3fca8cfb 100644
--- a/3d-viewer/3d_viewer/tools/eda_3d_actions.h
+++ b/3d-viewer/3d_viewer/tools/eda_3d_actions.h
@@ -42,6 +42,13 @@ class EDA_3D_ACTIONS : public ACTIONS
 public:
     static TOOL_ACTION controlActivate;
 
+    static TOOL_ACTION reloadBoard;
+    static TOOL_ACTION toggleRaytacing;
+
+    static TOOL_ACTION copyToClipboard;
+    static TOOL_ACTION exportAsPNG;
+    static TOOL_ACTION exportAsJPEG;
+
     static TOOL_ACTION pivotCenter;
     static TOOL_ACTION rotateXCW;
     static TOOL_ACTION rotateXCCW;
diff --git a/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp b/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp
index ecc76bea53..5a26032e24 100644
--- a/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp
+++ b/3d-viewer/3d_viewer/tools/eda_3d_controller.cpp
@@ -334,11 +334,65 @@ int EDA_3D_CONTROLLER::ZoomFitScreen( const TOOL_EVENT& aEvent )
 }
 
 
+int EDA_3D_CONTROLLER::ReloadBoard( const TOOL_EVENT& aEvent )
+{
+    EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
+
+    if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
+        static_cast<EDA_3D_VIEWER_FRAME*>( frame )->NewDisplay( true );
+
+    return 0;
+}
+
+
+int EDA_3D_CONTROLLER::ToggleRaytracing( const TOOL_EVENT& aEvent )
+{
+    EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
+
+    if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
+    {
+        EDA_3D_VIEWER_FRAME* frame3d = static_cast<EDA_3D_VIEWER_FRAME*>( frame );
+
+        RENDER_ENGINE& engine = frame3d->GetAdapter().m_Cfg->m_Render.engine;
+        RENDER_ENGINE  old_engine = engine;
+
+        if( old_engine == RENDER_ENGINE::OPENGL )
+            engine = RENDER_ENGINE::RAYTRACING;
+        else
+            engine = RENDER_ENGINE::OPENGL;
+
+        // Directly tell the canvas the rendering engine changed
+        if( old_engine != engine )
+            frame3d->GetCanvas()->RenderEngineChanged();
+    }
+
+    return 0;
+}
+
+
+int EDA_3D_CONTROLLER::ExportImage( const TOOL_EVENT& aEvent )
+{
+    EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
+
+    if( frame && frame->GetFrameType() == FRAME_PCB_DISPLAY3D )
+        static_cast<EDA_3D_VIEWER_FRAME*>( frame )->TakeScreenshot( aEvent.Parameter<EDA_3D_VIEWER_EXPORT_FORMAT>() );
+
+    return 0;
+}
+
+
 void EDA_3D_CONTROLLER::setTransitions()
 {
     Go( &EDA_3D_CONTROLLER::Main,               EDA_3D_ACTIONS::controlActivate.MakeEvent() );
     Go( &EDA_3D_CONTROLLER::UpdateMenu,         ACTIONS::updateMenu.MakeEvent() );
 
+    // Miscellaneous control
+    Go( &EDA_3D_CONTROLLER::ReloadBoard,        EDA_3D_ACTIONS::reloadBoard.MakeEvent() );
+    Go( &EDA_3D_CONTROLLER::ToggleRaytracing,   EDA_3D_ACTIONS::toggleRaytacing.MakeEvent() );
+    Go( &EDA_3D_CONTROLLER::ExportImage,        EDA_3D_ACTIONS::copyToClipboard.MakeEvent() );
+    Go( &EDA_3D_CONTROLLER::ExportImage,        EDA_3D_ACTIONS::exportAsPNG.MakeEvent() );
+    Go( &EDA_3D_CONTROLLER::ExportImage,        EDA_3D_ACTIONS::exportAsJPEG.MakeEvent() );
+
     // Pan control
     Go( &EDA_3D_CONTROLLER::PanControl,         ACTIONS::panUp.MakeEvent() );
     Go( &EDA_3D_CONTROLLER::PanControl,         ACTIONS::panDown.MakeEvent() );
diff --git a/3d-viewer/3d_viewer/tools/eda_3d_controller.h b/3d-viewer/3d_viewer/tools/eda_3d_controller.h
index 4e793cdbb7..c1e620e429 100644
--- a/3d-viewer/3d_viewer/tools/eda_3d_controller.h
+++ b/3d-viewer/3d_viewer/tools/eda_3d_controller.h
@@ -96,6 +96,10 @@ public:
     int ToggleVisibility( const TOOL_EVENT& aEvent );
     int ToggleLayersManager( const TOOL_EVENT& aEvent );
 
+    int ReloadBoard( const TOOL_EVENT& aEvent );
+    int ToggleRaytracing( const TOOL_EVENT& aEvent );
+    int ExportImage( const TOOL_EVENT& aEvent );
+
 private:
     /// Set up handlers for various events.
     void setTransitions() override;
diff --git a/3d-viewer/3d_viewer_id.h b/3d-viewer/3d_viewer_id.h
index 9c5056f914..ba681e7b16 100644
--- a/3d-viewer/3d_viewer_id.h
+++ b/3d-viewer/3d_viewer_id.h
@@ -34,20 +34,12 @@
 enum id_3dview_frm
 {
     ID_START_COMMAND_3D = ID_KICAD_3D_VIEWER_START,
-    ID_RELOAD3D_BOARD,
-    ID_TOOL_SCREENCOPY_TOCLIBBOARD,
-
-    ID_MENU_SCREENCOPY_PNG,
-    ID_MENU_SCREENCOPY_JPEG,
-    ID_MENU_SCREENCOPY_TOCLIBBOARD,
 
     ID_MENU3D_RESET_DEFAULTS,
 
     // Help
     ID_MENU_COMMAND_END,
 
-    ID_RENDER_CURRENT_VIEW,
-
     ID_DISABLE_RAY_TRACING,
 
     ID_CUSTOM_EVENT_1,      // A id for a custom event (canvas refresh request)