]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/mainframe.cpp
Merge commit '00a7e0326354f7837338661c2307412f5beba9fb' into master-merge
[xonotic/netradiant.git] / radiant / mainframe.cpp
index 6f377579f484b3015ce5876c606a19e35b1e3023..41e9461e5046007f29658be29691819f54c46c9b 100644 (file)
 #include "feedback.h"
 #include "referencecache.h"
 #include "texwindow.h"
+#include "filterbar.h"
 
+#if GDEF_OS_WINDOWS
+#include <process.h>
+#else
+#include <spawn.h>
+#endif
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+/* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
+#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget) g_object_set_data( G_OBJECT( window ), "glwidget", G_OBJECT( widget ) )
+#else
+#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget)
+#endif
+
+#define GARUX_DISABLE_GTKTHEME
+#ifndef GARUX_DISABLE_GTKTHEME
+#include "gtktheme.h"
+#endif
 
 struct layout_globals_t
 {
@@ -155,6 +173,8 @@ void VFS_Refresh(){
        RefreshReferences();
        // also refresh texture browser
        TextureBrowser_RefreshShaders();
+       // also show textures (all or common)
+       TextureBrowser_ShowStartupShaders( GlobalTextureBrowser() );
 }
 
 void VFS_Restart(){
@@ -213,9 +233,7 @@ void HomePaths_Realise(){
                        }
                        path.clear();
                        path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
-#endif
-
-#if GDEF_OS_WINDOWS
+#elif GDEF_OS_WINDOWS
                        TCHAR mydocsdir[MAX_PATH + 1];
                        wchar_t *mydocsdirw;
                        HMODULE shfolder = LoadLibrary( "shfolder.dll" );
@@ -252,13 +270,19 @@ void HomePaths_Realise(){
                                        break;
                                }
                        }
-#endif
-
-#if GDEF_OS_POSIX
+#elif GDEF_OS_XDG
+                       path.clear();
+                       path << DirectoryCleaned( g_get_user_data_dir() ) << ( prefix + 1 ) << "/";
+                       if ( file_exists( path.c_str() ) && file_is_directory( path.c_str() ) ) {
+                               g_qeglobals.m_userEnginePath = path.c_str();
+                               break;
+                       }
+                       else {
                        path.clear();
                        path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
                        g_qeglobals.m_userEnginePath = path.c_str();
                        break;
+                       }
 #endif
                }
 
@@ -434,14 +458,32 @@ void setPakPath( int num, const char* path ){
 }
 
 
-// App Path
+// executable file path (full path)
+CopiedString g_strAppFilePath;
+
+// directory paths
+CopiedString g_strAppPath; 
+CopiedString g_strLibPath;
+CopiedString g_strDataPath;
 
-CopiedString g_strAppPath;                 ///< holds the full path of the executable
+const char* AppFilePath_get(){
+       return g_strAppFilePath.c_str();
+}
 
 const char* AppPath_get(){
        return g_strAppPath.c_str();
 }
 
+const char *LibPath_get()
+{
+    return g_strLibPath.c_str();
+}
+
+const char *DataPath_get()
+{
+    return g_strDataPath.c_str();
+}
+
 /// the path to the local rc-dir
 const char* LocalRcPath_get( void ){
        static CopiedString rc_path;
@@ -540,39 +582,28 @@ struct PakPath4 {
 bool g_disableEnginePath = false;
 bool g_disableHomePath = false;
 
-void Paths_constructPreferences( PreferencesPage& page ){
+void Paths_constructBasicPreferences(  PreferencesPage& page ) {
        page.appendPathEntry( "Engine Path", true, make_property<EnginePath>(g_strEnginePath) );
+}
 
-       page.appendCheckBox(
-               "", "Do not use Engine Path",
-               g_disableEnginePath
-                                                 );
+void Paths_constructPreferences( PreferencesPage& page ){
+       Paths_constructBasicPreferences( page );
 
-       page.appendCheckBox(
-               "", "Do not use Home Path",
-               g_disableHomePath
-               );
+       page.appendSpacer( 4 );
+       page.appendLabel( "", "Advanced options" );
+       page.appendCheckBox( "", "Do not use Engine Path", g_disableEnginePath );
+       page.appendCheckBox( "", "Do not use Home Path", g_disableHomePath );
 
-       for ( int i = 0; i < g_pakPathCount; i++ ) {
-               std::string label = "Pak Path " + std::to_string(i);
-               switch (i) {
-                       case 0:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath0>( g_strPakPath[i] ) );
-                       break;
-                       case 1:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath1>( g_strPakPath[i] ) );
-                       break;
-                       case 2:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath2>( g_strPakPath[i] ) );
-                       break;
-                       case 3:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath3>( g_strPakPath[i] ) );
-                       break;
-                       case 4:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath4>( g_strPakPath[i] ) );
-                       break;
-}
-       }
+       page.appendSpacer( 4 );
+       page.appendLabel( "", "Only a very few games support Pak Paths," );
+       page.appendLabel( "", "if you don't know what it is, leave this blank." );
+
+       const char *label = "Pak Path ";
+       page.appendPathEntry( label, true, make_property<PakPath0>( g_strPakPath[0] ) );
+       page.appendPathEntry( label, true, make_property<PakPath1>( g_strPakPath[1] ) );
+       page.appendPathEntry( label, true, make_property<PakPath2>( g_strPakPath[2] ) );
+       page.appendPathEntry( label, true, make_property<PakPath3>( g_strPakPath[3] ) );
+       page.appendPathEntry( label, true, make_property<PakPath4>( g_strPakPath[4] ) );
 }
 
 void Paths_constructPage( PreferenceGroup& group ){
@@ -589,14 +620,14 @@ class PathsDialog : public Dialog
 {
 public:
 ui::Window BuildDialog(){
-       auto frame = create_dialog_frame( "Path settings", ui::Shadow::ETCHED_IN );
+       auto frame = create_dialog_frame( "Path Settings", ui::Shadow::ETCHED_IN );
 
        auto vbox2 = create_dialog_vbox( 0, 4 );
        frame.add(vbox2);
 
        {
-               PreferencesPage preferencesPage( *this, vbox2 );
-               Paths_constructPreferences( preferencesPage );
+               PreferencesPage page( *this, vbox2 );
+               Paths_constructBasicPreferences( page );
        }
 
        return ui::Window(create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, frame ));
@@ -755,7 +786,7 @@ void Radiant_detachGameToolsPathObserver( ModuleObserver& observer ){
 void Radiant_Initialise(){
        GlobalModuleServer_Initialise();
 
-       Radiant_loadModulesFromRoot( AppPath_get() );
+       Radiant_loadModulesFromRoot( LibPath_get() );
 
        Preferences_Load();
 
@@ -784,7 +815,7 @@ void Radiant_Shutdown(){
 }
 
 void Exit(){
-       if ( ConfirmModified( "Exit Radiant" ) ) {
+       if ( ConfirmModified( "Exit " RADIANT_NAME ) ) {
                gtk_main_quit();
        }
 }
@@ -945,6 +976,53 @@ void ColorScheme_Ydnar(){
        XY_UpdateAllWindows();
 }
 
+/* color scheme to fit the GTK Adwaita Dark theme */
+void ColorScheme_AdwaitaDark()
+{
+       // SI_Colors0
+       // GlobalTextureBrowser().color_textureback
+       TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f));
+
+       // SI_Colors4
+       g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f);
+       // SI_Colors12
+       g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f);
+       CamWnd_Update(*g_pParentWnd->GetCamWnd());
+
+       // SI_Colors1
+       g_xywindow_globals.color_gridback = Vector3(0.25f, 0.25f, 0.25f);
+       // SI_Colors2
+       g_xywindow_globals.color_gridminor = Vector3(0.21f, 0.23f, 0.23f);
+       // SI_Colors3
+       g_xywindow_globals.color_gridmajor = Vector3(0.14f, 0.15f, 0.15f);
+       // SI_Colors14
+       g_xywindow_globals.color_gridmajor_alt = Vector3(1.0f, 0.0f, 0.0f);
+       // SI_Colors6
+       g_xywindow_globals.color_gridblock = Vector3(1.0f, 1.0f, 1.0f);
+       // SI_Colors7
+       g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f);
+       // ??
+       g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f);
+       // ??
+       g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f);
+       // SI_Colors8
+       g_xywindow_globals.color_brushes = Vector3(0.73f, 0.73f, 0.73f);
+
+       // SI_AxisColors0
+       g_xywindow_globals.AxisColorX = Vector3(1.0f, 0.0f, 0.0f);
+       // SI_AxisColors1
+       g_xywindow_globals.AxisColorY = Vector3(0.0f, 1.0f, 0.0f);
+       // SI_AxisColors2
+       g_xywindow_globals.AxisColorZ = Vector3(0.0f, 0.0f, 1.0f);
+       SetWorldspawnColour(g_xywindow_globals.color_brushes);
+       // ??
+       g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f);
+       XY_UpdateAllWindows();
+
+       // SI_Colors5
+       // g_entity_globals.color_entity = Vector3(0.0f, 0.0f, 0.0f);
+}
+
 typedef Callback<void(Vector3&)> GetColourCallback;
 typedef Callback<void(const Vector3&)> SetColourCallback;
 
@@ -1062,6 +1140,11 @@ ui::MenuItem create_colours_menu(){
        create_menu_item_with_mnemonic( menu_3, "Q3Radiant Original", "ColorSchemeQER" );
        create_menu_item_with_mnemonic( menu_3, "Black and Green", "ColorSchemeBlackAndGreen" );
        create_menu_item_with_mnemonic( menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar" );
+       create_menu_item_with_mnemonic(menu_3, "Adwaita Dark", "ColorSchemeAdwaitaDark");
+
+#ifndef GARUX_DISABLE_GTKTHEME
+       create_menu_item_with_mnemonic( menu_in_menu, "GTK Theme...", "gtkThemeDlg" );
+#endif
 
        menu_separator( menu_in_menu );
 
@@ -1735,9 +1818,11 @@ void Selection_SnapToGrid(){
 
 
 static gint qe_every_second( gpointer data ){
-       GdkModifierType mask;
+       if (g_pParentWnd == nullptr)
+               return TRUE;
 
-       gdk_window_get_pointer( 0, 0, 0, &mask );
+       GdkModifierType mask;
+       gdk_window_get_pointer( gtk_widget_get_window(g_pParentWnd->m_window), nullptr, nullptr, &mask );
 
        if ( ( mask & ( GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK ) ) == 0 ) {
                QE_CheckAutoSave();
@@ -1849,15 +1934,18 @@ void ScreenUpdates_Disable( const char* message, const char* title ){
                bool isActiveApp = MainFrame_isActiveApp();
 
                g_wait = create_wait_dialog( title, message );
-               gtk_grab_add( g_wait.m_window  );
 
                if ( isActiveApp ) {
                        g_wait.m_window.show();
+                       gtk_grab_add( g_wait.m_window  );
                        ScreenUpdates_process();
                }
        }
        else if ( g_wait.m_window.visible() ) {
                g_wait.m_label.text(message);
+               if ( GTK_IS_WINDOW(g_wait.m_window) ) {
+                       gtk_grab_add(g_wait.m_window);
+               }
                ScreenUpdates_process();
        }
        g_wait_stack.push_back( message );
@@ -1961,18 +2049,18 @@ ui::MenuItem create_file_menu(){
 #endif
 
        create_menu_item_with_mnemonic( menu, "_Open...", "OpenMap" );
-
        create_menu_item_with_mnemonic( menu, "_Import...", "ImportMap" );
+       menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "_Save", "SaveMap" );
        create_menu_item_with_mnemonic( menu, "Save _as...", "SaveMapAs" );
        create_menu_item_with_mnemonic( menu, "_Export selected...", "ExportSelected" );
-       menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "Save re_gion...", "SaveRegion" );
+       menu_separator( menu );
 //     menu_separator( menu );
 //     create_menu_item_with_mnemonic( menu, "_Refresh models", "RefreshReferences" );
 //     menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "Pro_ject settings...", "ProjectSettings" );
-       menu_separator( menu );
+       //menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "_Pointfile...", "TogglePointfile" );
        menu_separator( menu );
        MRU_constructMenu( menu );
@@ -2000,8 +2088,6 @@ ui::MenuItem create_edit_menu(){
        create_menu_item_with_mnemonic( menu, "_Duplicate", "CloneSelection" );
        create_menu_item_with_mnemonic( menu, "Duplicate, make uni_que", "CloneSelectionAndMakeUnique" );
        create_menu_item_with_mnemonic( menu, "D_elete", "DeleteSelection" );
-       menu_separator( menu );
-       create_menu_item_with_mnemonic( menu, "Snap To Grid", "SnapToGrid" );
        //create_menu_item_with_mnemonic( menu, "Pa_rent", "ParentSelection" );
        menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "C_lear Selection", "UnSelectSelection" );
@@ -2084,6 +2170,9 @@ ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){
                create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane In", "CubicClipZoomIn" );
                create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane Out", "CubicClipZoomOut" );
                menu_separator( camera_menu );
+               create_menu_item_with_mnemonic( camera_menu, "Decrease FOV", "FOVDec" );
+               create_menu_item_with_mnemonic( camera_menu, "Increase FOV", "FOVInc" );
+               menu_separator( camera_menu );
                create_menu_item_with_mnemonic( camera_menu, "Next leak spot", "NextLeakSpot" );
                create_menu_item_with_mnemonic( camera_menu, "Previous leak spot", "PrevLeakSpot" );
                menu_separator( camera_menu );
@@ -2187,6 +2276,9 @@ ui::MenuItem create_selection_menu(){
                create_check_menu_item_with_mnemonic( menu_in_menu, "_Faces", "DragFaces" );
        }
 
+       menu_separator( menu );
+       create_menu_item_with_mnemonic( menu, "Snap To Grid", "SnapToGrid" );
+
        menu_separator( menu );
 
        {
@@ -2333,7 +2425,7 @@ ui::MenuItem create_help_menu(){
 
        create_menu_item_with_mnemonic( menu, "Bug report", makeCallbackF(OpenBugReportURL) );
        create_menu_item_with_mnemonic( menu, "Shortcuts list", makeCallbackF(DoCommandListDlg) );
-       create_menu_item_with_mnemonic( menu, "_About", makeCallbackF(DoAbout) );
+       create_menu_item_with_mnemonic( menu, "_About...", makeCallbackF(DoAbout) );
 
        return help_menu_item;
 }
@@ -2371,7 +2463,7 @@ void Patch_registerShortcuts(){
        command_connect_accelerator( "PatchDeleteLastColumn" );
        command_connect_accelerator( "PatchDeleteLastRow" );
        command_connect_accelerator( "NaturalizePatch" );
-       //command_connect_accelerator("CapCurrentCurve");
+       command_connect_accelerator( "CapCurrentCurve");
 }
 
 void Manipulators_registerShortcuts(){
@@ -2402,6 +2494,8 @@ void SelectNudge_registerShortcuts(){
        //command_connect_accelerator("SelectNudgeRight");
        //command_connect_accelerator("SelectNudgeUp");
        //command_connect_accelerator("SelectNudgeDown");
+       command_connect_accelerator( "UnSelectSelection2" );
+       command_connect_accelerator( "DeleteSelection2" );
 }
 
 void SnapToGrid_registerShortcuts(){
@@ -2417,18 +2511,26 @@ void SurfaceInspector_registerShortcuts(){
 }
 
 
+void TexBro_registerShortcuts(){
+       command_connect_accelerator( "FindReplaceTextures" );
+       command_connect_accelerator( "RefreshShaders" );
+       //refresh models
+       command_connect_accelerator( "RefreshReferences" );
+}
+
 void register_shortcuts(){
-       PatchInspector_registerShortcuts();
-       Patch_registerShortcuts();
+//     PatchInspector_registerShortcuts();
+       //Patch_registerShortcuts();
        Grid_registerShortcuts();
-       XYWnd_registerShortcuts();
+//     XYWnd_registerShortcuts();
        CamWnd_registerShortcuts();
        Manipulators_registerShortcuts();
        SurfaceInspector_registerShortcuts();
        TexdefNudge_registerShortcuts();
        SelectNudge_registerShortcuts();
-       SnapToGrid_registerShortcuts();
-       SelectByType_registerShortcuts();
+//     SnapToGrid_registerShortcuts();
+//     SelectByType_registerShortcuts();
+       TexBro_registerShortcuts();
 }
 
 void File_constructToolbar( ui::Toolbar toolbar ){
@@ -2458,8 +2560,8 @@ void Select_constructToolbar( ui::Toolbar toolbar ){
 void CSG_constructToolbar( ui::Toolbar toolbar ){
        toolbar_append_button( toolbar, "CSG Subtract (SHIFT + U)", "selection_csgsubtract.png", "CSGSubtract" );
        toolbar_append_button( toolbar, "CSG Merge (CTRL + U)", "selection_csgmerge.png", "CSGMerge" );
-       toolbar_append_button( toolbar, "Make Hollow", "selection_makehollow.png", "CSGHollow" );
        toolbar_append_button( toolbar, "Make Room", "selection_makeroom.png", "CSGRoom" );
+       toolbar_append_button( toolbar, "CSG Tool", "ellipsis.png", "CSGTool" );
 }
 
 void ComponentModes_constructToolbar( ui::Toolbar toolbar ){
@@ -2474,7 +2576,7 @@ void Clipper_constructToolbar( ui::Toolbar toolbar ){
 }
 
 void XYWnd_constructToolbar( ui::Toolbar toolbar ){
-       toolbar_append_button( toolbar, "Change views", "view_change.png", "NextView" );
+       toolbar_append_button( toolbar, "Change views (CTRL + TAB)", "view_change.png", "NextView" );
 }
 
 void Manipulators_constructToolbar( ui::Toolbar toolbar ){
@@ -2521,7 +2623,7 @@ ui::Toolbar create_main_toolbar( MainFrame::EViewStyle style ){
 
        ComponentModes_constructToolbar( toolbar );
 
-       if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating ) {
+       if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft ) {
                space();
 
                XYWnd_constructToolbar( toolbar );
@@ -2548,21 +2650,16 @@ ui::Toolbar create_main_toolbar( MainFrame::EViewStyle style ){
        space();
 
        /*auto g_view_entities_button =*/ toolbar_append_button( toolbar, "Entities (N)", "entities.png", "ToggleEntityInspector" );
-       auto g_view_console_button = toolbar_append_button( toolbar, "Console (O)", "console.png", "ToggleConsole" );
-       auto g_view_textures_button = toolbar_append_button( toolbar, "Texture Browser (T)", "texture_browser.png", "ToggleTextures" );
+       if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft ) {
+               auto g_view_console_button = toolbar_append_button( toolbar, "Console (O)", "console.png", "ToggleConsole" );
+               auto g_view_textures_button = toolbar_append_button( toolbar, "Texture Browser (T)", "texture_browser.png", "ToggleTextures" );
+       }
        // TODO: call light inspector
        //GtkButton* g_view_lightinspector_button = toolbar_append_button(toolbar, "Light Inspector", "lightinspector.png", "ToggleLightInspector");
 
        space();
        /*auto g_refresh_models_button =*/ toolbar_append_button( toolbar, "Refresh Models", "refresh_models.png", "RefreshReferences" );
 
-
-       // disable the console and texture button in the regular layouts
-       if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft ) {
-               gtk_widget_set_sensitive( g_view_console_button , FALSE );
-               gtk_widget_set_sensitive( g_view_textures_button , FALSE );
-       }
-
        return toolbar;
 }
 
@@ -2712,10 +2809,14 @@ MainFrame::~MainFrame(){
 
        for ( std::vector<ui::Widget>::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i )
        {
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
                i->destroy();
+#endif
        }
 
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
        m_window.destroy();
+#endif
 }
 
 void MainFrame::SetActiveXY( XYWnd* p ){
@@ -2872,13 +2973,16 @@ WindowPositionTracker g_posXZWnd;
 WindowPositionTracker g_posYZWnd;
 
 static gint mainframe_delete( ui::Widget widget, GdkEvent *event, gpointer data ){
-       if ( ConfirmModified( "Exit Radiant" ) ) {
+       if ( ConfirmModified( "Exit " RADIANT_NAME ) ) {
                gtk_main_quit();
        }
 
        return TRUE;
 }
 
+PanedState g_single_hpaned = { 0.75f, -1, };
+PanedState g_single_vpaned = { 0.75f, -1, };
+
 void MainFrame::Create(){
        ui::Window window = ui::Window( ui::window_type::TOP );
 
@@ -2913,6 +3017,7 @@ void MainFrame::Create(){
        auto vbox = ui::VBox( FALSE, 0 );
        window.add(vbox);
        vbox.show();
+       gtk_container_set_focus_chain( GTK_CONTAINER( vbox ), NULL );
 
        global_accel_connect_window( window );
 
@@ -2926,47 +3031,38 @@ void MainFrame::Create(){
     auto main_toolbar = create_main_toolbar( CurrentStyle() );
        vbox.pack_start( main_toolbar, FALSE, FALSE, 0 );
 
-       auto plugin_toolbar = create_plugin_toolbar();
-       if ( !g_Layout_enablePluginToolbar.m_value ) {
-               plugin_toolbar.hide();
+       if ( g_Layout_enablePluginToolbar.m_value || g_Layout_enableFilterToolbar.m_value ){
+               auto PFbox = ui::HBox( FALSE, 3 );
+               vbox.pack_start( PFbox, FALSE, FALSE, 0 );
+               PFbox.show();
+               if ( g_Layout_enablePluginToolbar.m_value ){
+                       auto plugin_toolbar = create_plugin_toolbar();
+                       if ( g_Layout_enableFilterToolbar.m_value ){
+                               PFbox.pack_start( plugin_toolbar, FALSE, FALSE, 0 );
+                       }
+                       else{
+                               PFbox.pack_start( plugin_toolbar, TRUE, TRUE, 0 );
+                       }
+               }
+               if ( g_Layout_enableFilterToolbar.m_value ){
+                       ui::Toolbar filter_toolbar = create_filter_toolbar();
+                       PFbox.pack_start( filter_toolbar, TRUE, TRUE, 0 );
+               }
        }
 
-       if ( g_Layout_enableFilterToolbar.m_value ) {
-               auto space = [&]() {
-                       auto btn = gtk_separator_tool_item_new();
-                               gtk_widget_show(GTK_WIDGET(btn));
-                               gtk_container_add(GTK_CONTAINER(plugin_toolbar), GTK_WIDGET(btn));
-               };
-
-               space();
-               toolbar_append_toggle_button( plugin_toolbar, "World (ALT + 1)", "f-world.bmp", "FilterWorldBrushes" );
-               toolbar_append_toggle_button( plugin_toolbar, "Details (CTRL + D)", "f-details.bmp", "FilterDetails" );
-               toolbar_append_toggle_button( plugin_toolbar, "Structural (CTRL + SHIFT + D)", "f-structural.bmp", "FilterStructural" );
-               toolbar_append_toggle_button( plugin_toolbar, "Patches (CTRL + P)", "patch_wireframe.png", "FilterPatches" );
-               space();
-               toolbar_append_toggle_button( plugin_toolbar, "Areaportals (ALT + 3)", "f-areaportal.bmp", "FilterAreaportals" );
-               toolbar_append_toggle_button( plugin_toolbar, "Translucent (ALT + 4)", "f-translucent.bmp", "FilterTranslucent" );
-               toolbar_append_toggle_button( plugin_toolbar, "Liquids (ALT + 5)", "f-liquids.bmp", "FilterLiquids" );
-               toolbar_append_toggle_button( plugin_toolbar, "Caulk (ALT + 6)", "f-caulk.bmp", "FilterCaulk" );
-               toolbar_append_toggle_button( plugin_toolbar, "Clips (ALT + 7)", "f-clip.bmp", "FilterClips" );
-               toolbar_append_toggle_button( plugin_toolbar, "HintsSkips (CTRL + H)", "f-hint.bmp", "FilterHintsSkips" );
-               //toolbar_append_toggle_button( plugin_toolbar, "Paths (ALT + 8)", "texture_lock.bmp", "FilterPaths" );
-               space();
-               toolbar_append_toggle_button( plugin_toolbar, "Entities (ALT + 2)", "f-entities.bmp", "FilterEntities" );
-               toolbar_append_toggle_button( plugin_toolbar, "Lights (ALT + 0)", "lightinspector.png", "FilterLights" );
-               toolbar_append_toggle_button( plugin_toolbar, "Models (SHIFT + M)", "f-models.bmp", "FilterModels" );
-               toolbar_append_toggle_button( plugin_toolbar, "Triggers (CTRL + SHIFT + T)", "f-triggers.bmp", "FilterTriggers" );
-               toolbar_append_toggle_button( plugin_toolbar, "Decals (SHIFT + D)", "f-decals.bmp", "FilterDecals" );
-               space();
-               toolbar_append_button( plugin_toolbar, "InvertFilters", "f-invert.bmp", "InvertFilters" );
-               toolbar_append_button( plugin_toolbar, "ResetFilters", "f-reset.bmp", "ResetFilters" );
-       }
-       vbox.pack_start( plugin_toolbar, FALSE, FALSE, 0 );
+       /*GtkToolbar* plugin_toolbar = create_plugin_toolbar();
+       if ( !g_Layout_enablePluginToolbar.m_value ) {
+               gtk_widget_hide( GTK_WIDGET( plugin_toolbar ) );
+       }*/
 
        ui::Widget main_statusbar = create_main_statusbar(reinterpret_cast<ui::Widget *>(m_pStatusLabel));
        vbox.pack_end(main_statusbar, FALSE, TRUE, 2);
 
        GroupDialog_constructWindow( window );
+
+       /* want to realize it immediately; otherwise gtk paned splits positions wont be set correctly for floating group dlg */
+       gtk_widget_realize ( GTK_WIDGET( GroupDialog_getWindow() ) );
+
        g_page_entity = GroupDialog_addPage( "Entities", EntityInspector_constructWindow( GroupDialog_getWindow() ), RawStringExportCaller( "Entities" ) );
 
        if ( FloatingGroupDialog() ) {
@@ -2994,19 +3090,24 @@ void MainFrame::Create(){
 
        window.show();
 
-       if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft ) {
+       if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft )
+       {
                {
                        ui::Widget hsplit = ui::HPaned(ui::New);
-                       m_vSplit = hsplit;
+                       m_hSplit = hsplit;
+
                        vbox.pack_start( hsplit, TRUE, TRUE, 0 );
                        hsplit.show();
+
                        {
                                ui::Widget vsplit = ui::VPaned(ui::New);
                                vsplit.show();
                                m_vSplit = vsplit;
+
                                ui::Widget vsplit2 = ui::VPaned(ui::New);
                                vsplit2.show();
-                               m_vSplit = vsplit2;
+                               m_vSplit2 = vsplit2;
+
                                if ( CurrentStyle() == eRegular ){
                                        gtk_paned_add1( GTK_PANED( hsplit ), vsplit );
                                        gtk_paned_add2( GTK_PANED( hsplit ), vsplit2 );
@@ -3024,8 +3125,8 @@ void MainFrame::Create(){
                                m_pXYWnd = new XYWnd();
                                m_pXYWnd->SetViewType( XY );
                                ui::Widget xy_window = ui::Widget(create_framed_widget( m_pXYWnd->GetWidget( ) ));
-
                                gtk_paned_add1( GTK_PANED( vsplit ), xy_window );
+
                                {
                                        // camera
                                        m_pCamWnd = NewCamWnd();
@@ -3055,7 +3156,8 @@ void MainFrame::Create(){
 
                gtk_paned_set_position( GTK_PANED( m_vSplit2 ), g_layout_globals.nCamHeight );
        }
-       else if ( CurrentStyle() == eFloating ) {
+       else if ( CurrentStyle() == eFloating )
+       {
                {
                        ui::Window window = ui::Window(create_persistent_floating_window( "Camera", m_window ));
                        global_accel_connect_window( window );
@@ -3072,6 +3174,8 @@ void MainFrame::Create(){
                        }
                        CamWnd_setParent( *m_pCamWnd, window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, CamWnd_getWidget( *m_pCamWnd ) );
+
                        g_floating_windows.push_back( window );
                }
 
@@ -3091,6 +3195,8 @@ void MainFrame::Create(){
                        }
                        XY_Top_Shown_Construct( window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXYWnd->GetWidget() );
+
                        g_floating_windows.push_back( window );
                }
 
@@ -3110,6 +3216,8 @@ void MainFrame::Create(){
 
                        XZ_Front_Shown_Construct( window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXZWnd->GetWidget() );
+
                        g_floating_windows.push_back( window );
                }
 
@@ -3129,17 +3237,21 @@ void MainFrame::Create(){
 
                        YZ_Side_Shown_Construct( window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pYZWnd->GetWidget() );
+
                        g_floating_windows.push_back( window );
                }
 
                {
                        auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) );
                        g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() );
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( GroupDialog_getWindow(), TextureBrowser_getGLWidget() );
                }
 
                GroupDialog_show();
        }
-       else // 4 way
+       else if ( CurrentStyle() == eSplit )
        {
                m_pCamWnd = NewCamWnd();
                GlobalCamera_setCamWnd( *m_pCamWnd );
@@ -3166,10 +3278,62 @@ void MainFrame::Create(){
                vbox.pack_start( split, TRUE, TRUE, 0 );
 
                {
-            auto frame = create_framed_widget( TextureBrowser_constructWindow( window ) );
+            auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) );
                        g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() );
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, TextureBrowser_getGLWidget() );
                }
        }
+       else // single window
+       {
+               m_pCamWnd = NewCamWnd();
+               GlobalCamera_setCamWnd( *m_pCamWnd );
+               CamWnd_setParent( *m_pCamWnd, window );
+
+               ui::Widget camera = CamWnd_getWidget( *m_pCamWnd );
+
+               m_pYZWnd = new XYWnd();
+               m_pYZWnd->SetViewType( YZ );
+
+               ui::Widget yz = m_pYZWnd->GetWidget();
+
+               m_pXYWnd = new XYWnd();
+               m_pXYWnd->SetViewType( XY );
+
+               ui::Widget xy = m_pXYWnd->GetWidget();
+
+               m_pXZWnd = new XYWnd();
+               m_pXZWnd->SetViewType( XZ );
+
+               ui::Widget xz = m_pXZWnd->GetWidget();
+
+               ui::Widget hsplit = ui::HPaned(ui::New);
+               vbox.pack_start( hsplit, TRUE, TRUE, 0 );
+               hsplit.show();
+
+               ui::Widget split = create_split_views( camera, yz, xy, xz );
+
+               ui::Widget vsplit = ui::VPaned(ui::New);
+               vsplit.show();
+
+               // textures
+               ui::Widget texture_window = create_framed_widget( TextureBrowser_constructWindow( window ) );
+
+               // console
+               ui::Widget console_window = create_framed_widget( Console_constructWindow( window ) );
+
+               gtk_paned_add1( GTK_PANED( hsplit ), split );
+               gtk_paned_add2( GTK_PANED( hsplit ), vsplit );
+
+               gtk_paned_add1( GTK_PANED( vsplit ), texture_window  );
+               gtk_paned_add2( GTK_PANED( vsplit ), console_window  );
+
+               hsplit.connect( "size_allocate", G_CALLBACK( hpaned_allocate ), &g_single_hpaned );
+               hsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_single_hpaned );
+
+               vsplit.connect( "size_allocate", G_CALLBACK( vpaned_allocate ), &g_single_vpaned );
+               vsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_single_vpaned );
+       }
 
        EntityList_constructWindow( window );
        PreferencesDialog_constructWindow( window );
@@ -3257,7 +3421,7 @@ void MainFrame::SetStatusText( CopiedString& status_text, const char* pText ){
 }
 
 void Sys_Status( const char* status ){
-       if ( g_pParentWnd != 0 ) {
+       if ( g_pParentWnd != nullptr ) {
                g_pParentWnd->SetStatusText( g_pParentWnd->m_command_status, status );
        }
 }
@@ -3289,7 +3453,7 @@ void MainFrame::SetGridStatus(){
 }
 
 void GridStatus_onTextureLockEnabledChanged(){
-       if ( g_pParentWnd != 0 ) {
+       if ( g_pParentWnd != nullptr ) {
                g_pParentWnd->SetGridStatus();
        }
 }
@@ -3334,7 +3498,7 @@ void GlobalGL_sharedContextDestroyed(){
 
 void Layout_constructPreferences( PreferencesPage& page ){
        {
-               const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png" };
+               const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png", "window5.png" };
                page.appendRadioIcons(
                        "Window Layout",
                        STRING_ARRAY_RANGE( layouts ),
@@ -3370,9 +3534,9 @@ void Layout_registerPreferencesPage(){
        PreferencesDialog_addInterfacePage( makeCallbackF(Layout_constructPage) );
 }
 
-
 #include "preferencesystem.h"
 #include "stringio.h"
+#include "transformpath/transformpath.h"
 
 void MainFrame_Construct(){
        GlobalCommands_insert( "OpenManual", makeCallbackF(OpenHelpURL), Accelerator( GDK_KEY_F1 ) );
@@ -3396,9 +3560,13 @@ void MainFrame_Construct(){
        GlobalCommands_insert( "PasteToCamera", makeCallbackF(PasteToCamera), Accelerator( 'V', (GdkModifierType)GDK_MOD1_MASK ) );
        GlobalCommands_insert( "CloneSelection", makeCallbackF(Selection_Clone), Accelerator( GDK_KEY_space ) );
        GlobalCommands_insert( "CloneSelectionAndMakeUnique", makeCallbackF(Selection_Clone_MakeUnique), Accelerator( GDK_KEY_space, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "DeleteSelection", makeCallbackF(deleteSelection), Accelerator( GDK_KEY_BackSpace ) );
+//     GlobalCommands_insert( "DeleteSelection", makeCallbackF(deleteSelection), Accelerator( GDK_KEY_BackSpace ) );
+       GlobalCommands_insert( "DeleteSelection2", makeCallbackF(deleteSelection), Accelerator( GDK_KEY_BackSpace ) );
+       GlobalCommands_insert( "DeleteSelection", makeCallbackF(deleteSelection), Accelerator( 'Z' ) );
        GlobalCommands_insert( "ParentSelection", makeCallbackF(Scene_parentSelected) );
-       GlobalCommands_insert( "UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator( GDK_KEY_Escape ) );
+//     GlobalCommands_insert( "UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator( GDK_KEY_Escape ) );
+       GlobalCommands_insert( "UnSelectSelection2", makeCallbackF(Selection_Deselect), Accelerator( GDK_KEY_Escape ) );
+       GlobalCommands_insert( "UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator( 'C' ) );
        GlobalCommands_insert( "InvertSelection", makeCallbackF(Select_Invert), Accelerator( 'I' ) );
        GlobalCommands_insert( "SelectInside", makeCallbackF(Select_Inside) );
        GlobalCommands_insert( "SelectTouching", makeCallbackF(Select_Touching) );
@@ -3440,10 +3608,14 @@ void MainFrame_Construct(){
        GlobalToggles_insert( "MouseScale", makeCallbackF(ScaleMode), ToggleItem::AddCallbackCaller( g_scalemode_button ) );
        GlobalToggles_insert( "MouseDrag", makeCallbackF(DragMode), ToggleItem::AddCallbackCaller( g_dragmode_button ), Accelerator( 'Q' ) );
 
+#ifndef GARUX_DISABLE_GTKTHEME
+       GlobalCommands_insert( "gtkThemeDlg", makeCallbackF(gtkThemeDlg) );
+#endif
        GlobalCommands_insert( "ColorSchemeOriginal", makeCallbackF(ColorScheme_Original) );
        GlobalCommands_insert( "ColorSchemeQER", makeCallbackF(ColorScheme_QER) );
        GlobalCommands_insert( "ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black) );
        GlobalCommands_insert( "ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar) );
+       GlobalCommands_insert("ColorSchemeAdwaitaDark", makeCallbackF(ColorScheme_AdwaitaDark));
        GlobalCommands_insert( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) );
        GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) );
        GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) );
@@ -3462,8 +3634,8 @@ void MainFrame_Construct(){
 
        GlobalCommands_insert( "CSGSubtract", makeCallbackF(CSG_Subtract), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) );
        GlobalCommands_insert( "CSGMerge", makeCallbackF(CSG_Merge), Accelerator( 'U', (GdkModifierType) GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "CSGHollow", makeCallbackF(CSG_MakeHollow) );
        GlobalCommands_insert( "CSGRoom", makeCallbackF(CSG_MakeRoom) );
+       GlobalCommands_insert( "CSGTool", makeCallbackF(CSG_Tool) );
 
        Grid_registerCommands();
 
@@ -3532,9 +3704,11 @@ void MainFrame_Construct(){
 #error "unknown platform"
 #endif
                ;
+
                StringOutputStream path( 256 );
                path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) );
-               g_strEnginePath = path.c_str();
+
+               g_strEnginePath = transformPath( path.c_str() ).c_str();
                GlobalPreferenceSystem().registerPreference( "EnginePath", make_property_string( g_strEnginePath ) );
        }
 
@@ -3559,8 +3733,7 @@ void MainFrame_Construct(){
        g_entityCount.setCountChangedCallback( makeCallbackF(QE_entityCountChanged) );
        GlobalEntityCreator().setCounter( &g_entityCount );
 
-       GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated;
-       GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed;
+       glwidget_set_shared_context_constructors( GlobalGL_sharedContextCreated, GlobalGL_sharedContextDestroyed);
 
        GlobalEntityClassManager().attach( g_WorldspawnColourEntityClassObserver );
 }
@@ -3580,3 +3753,61 @@ void GLWindow_Construct(){
 
 void GLWindow_Destroy(){
 }
+
+/* HACK: If ui::main is not called yet,
+gtk_main_quit will not quit, so tell main
+to not call ui::main. This happens when a
+map is loaded from command line and require
+a restart because of wrong format.
+Delete this when the code to not have to
+restart to load another format is merged. */
+extern bool g_dontStart;
+
+void Radiant_Restart(){
+       // preferences are expected to be already saved in any way
+       // this is just to be sure and be future proof
+       Preferences_Save();
+
+       // this asks user for saving if map is modified
+       // user can chose to not save, it's ok
+       ConfirmModified( "Restart " RADIANT_NAME );
+
+       int status;
+
+       char *argv[ 3 ];
+       char exe_file[ 256 ];
+       char map_file[ 256 ];
+       bool with_map = false;
+
+       strncpy( exe_file, g_strAppFilePath.c_str(), 256 );
+
+       if ( !Map_Unnamed( g_map ) ) {
+               strncpy( map_file, Map_Name( g_map ), 256 );
+               with_map = true;
+       }
+
+       argv[ 0 ] = exe_file;
+       argv[ 1 ] = with_map ? map_file : NULL;
+       argv[ 2 ] = NULL;
+
+#if GDEF_OS_WINDOWS
+       status = !_spawnvpe( P_NOWAIT, exe_file, argv, environ );
+#else
+       pid_t pid;
+
+       status = posix_spawn( &pid, exe_file, NULL, NULL, argv, environ );
+#endif
+
+       // quit if radiant successfully started
+       if ( status == 0 ) {
+               gtk_main_quit();
+               /* HACK: If ui::main is not called yet,
+               gtk_main_quit will not quit, so tell main
+               to not call ui::main. This happens when a
+               map is loaded from command line and require
+               a restart because of wrong format.
+               Delete this when the code to not have to
+               restart to load another format is merged. */
+               g_dontStart = true;
+       }
+}