]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/mainframe.cpp
radiant/q3map2: add option to disable engine path and home path
[xonotic/netradiant.git] / radiant / mainframe.cpp
index 433767d547c705bb2a04d0b521a9a4db820aa493..2eed7bff0c9f6a935cd146ee0410680b0f210a04 100644 (file)
@@ -371,6 +371,59 @@ void setEnginePath( const char* path ){
        }
 }
 
+// Pak Path
+
+CopiedString g_strPakPath[g_pakPathCount] = { "", "", "", "", "" };
+ModuleObservers g_pakPathObservers[g_pakPathCount];
+std::size_t g_pakpath_unrealised[g_pakPathCount] = { 1, 1, 1, 1, 1 };
+
+void Radiant_attachPakPathObserver( int num, ModuleObserver& observer ){
+       g_pakPathObservers[num].attach( observer );
+}
+
+void Radiant_detachPakPathObserver( int num, ModuleObserver& observer ){
+       g_pakPathObservers[num].detach( observer );
+}
+
+
+void PakPath_Realise( int num ){
+       if ( --g_pakpath_unrealised[num] == 0 ) {
+               g_pakPathObservers[num].realise();
+       }
+}
+
+const char* PakPath_get( int num ){
+       std::string message = "PakPath_get: pak path " + std::to_string(num) + " not realised";
+       ASSERT_MESSAGE( g_pakpath_unrealised[num] == 0, message.c_str() );
+       return g_strPakPath[num].c_str();
+}
+
+void PakPath_Unrealise( int num ){
+       if ( ++g_pakpath_unrealised[num] == 1 ) {
+               g_pakPathObservers[num].unrealise();
+       }
+}
+
+void setPakPath( int num, const char* path ){
+       if (!g_strcmp0( path, "")) {
+               g_strPakPath[num] = "";
+               return;
+       }
+
+       StringOutputStream buffer( 256 );
+       buffer << DirectoryCleaned( path );
+       if ( !path_equal( buffer.c_str(), g_strPakPath[num].c_str() ) ) {
+               std::string message = "Changing Pak Path " + std::to_string(num);
+               ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", message.c_str() );
+
+               PakPath_Unrealise(num);
+
+               g_strPakPath[num] = buffer.c_str();
+
+               PakPath_Realise(num);
+       }
+}
+
 
 // App Path
 
@@ -414,23 +467,105 @@ const char* GameToolsPath_get(){
        return g_strGameToolsPath.c_str();
 }
 
-void EnginePathImport( CopiedString& self, const char* value ){
+struct EnginePath {
+       static void Export(const CopiedString &self, const Callback<void(const char *)> &returnz) {
+               returnz(self.c_str());
+       }
+
+       static void Import(CopiedString &self, const char *value) {
        setEnginePath( value );
 }
-typedef ReferenceCaller1<CopiedString, const char*, EnginePathImport> EnginePathImportCaller;
+};
+
+struct PakPath0 {
+       static void Export( const CopiedString &self, const Callback<void(const char*)> &returnz ) {
+               returnz( self.c_str() );
+       }
+
+       static void Import( CopiedString &self, const char *value ) {
+               setPakPath( 0, value );
+       }
+};
+struct PakPath1 {
+       static void Export( const CopiedString &self, const Callback<void(const char*)> &returnz ) {
+               returnz( self.c_str() );
+       }
+
+       static void Import( CopiedString &self, const char *value ) {
+               setPakPath( 1, value );
+       }
+};
+struct PakPath2 {
+       static void Export( const CopiedString &self, const Callback<void(const char*)> &returnz ) {
+               returnz( self.c_str() );
+       }
+
+       static void Import( CopiedString &self, const char *value ) {
+               setPakPath( 2, value );
+       }
+};
+struct PakPath3 {
+       static void Export( const CopiedString &self, const Callback<void(const char*)> &returnz ) {
+               returnz( self.c_str() );
+       }
+
+       static void Import( CopiedString &self, const char *value ) {
+               setPakPath( 3, value );
+       }
+};
+struct PakPath4 {
+       static void Export( const CopiedString &self, const Callback<void(const char*)> &returnz ) {
+               returnz( self.c_str() );
+       }
+
+       static void Import( CopiedString &self, const char *value ) {
+               setPakPath( 4, value );
+       }
+};
+
+bool g_disableEnginePath = false;
+bool g_disableHomePath = false;
 
 void Paths_constructPreferences( PreferencesPage& page ){
-       page.appendPathEntry( "Engine Path", true,
-                                                 StringImportCallback( EnginePathImportCaller( g_strEnginePath ) ),
-                                                 StringExportCallback( StringExportCaller( g_strEnginePath ) )
-                                                 );
+       page.appendPathEntry( "Engine Path", true, make_property<EnginePath>(g_strEnginePath) );
+
+       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;
+               }
+       }
 }
 void Paths_constructPage( PreferenceGroup& group ){
        PreferencesPage page( group.createPage( "Paths", "Path Settings" ) );
        Paths_constructPreferences( page );
 }
 void Paths_registerPreferencesPage(){
-       PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Paths_constructPage>() );
+       PreferencesDialog_addSettingsPage( makeCallbackF(Paths_constructPage) );
 }
 
 
@@ -790,8 +925,8 @@ void ColorScheme_Ydnar(){
        XY_UpdateAllWindows();
 }
 
-typedef Callback1<Vector3&> GetColourCallback;
-typedef Callback1<const Vector3&> SetColourCallback;
+typedef Callback<void(Vector3&)> GetColourCallback;
+typedef Callback<void(const Vector3&)> SetColourCallback;
 
 class ChooseColour
 {
@@ -814,37 +949,37 @@ void operator()(){
 void Colour_get( const Vector3& colour, Vector3& other ){
        other = colour;
 }
-typedef ConstReferenceCaller1<Vector3, Vector3&, Colour_get> ColourGetCaller;
+typedef ConstReferenceCaller<Vector3, void(Vector3&), Colour_get> ColourGetCaller;
 
 void Colour_set( Vector3& colour, const Vector3& other ){
        colour = other;
        SceneChangeNotify();
 }
-typedef ReferenceCaller1<Vector3, const Vector3&, Colour_set> ColourSetCaller;
+typedef ReferenceCaller<Vector3, void(const Vector3&), Colour_set> ColourSetCaller;
 
 void BrushColour_set( const Vector3& other ){
        g_xywindow_globals.color_brushes = other;
        SetWorldspawnColour( g_xywindow_globals.color_brushes );
        SceneChangeNotify();
 }
-typedef FreeCaller1<const Vector3&, BrushColour_set> BrushColourSetCaller;
+typedef FreeCaller<void(const Vector3&), BrushColour_set> BrushColourSetCaller;
 
 void ClipperColour_set( const Vector3& other ){
        g_xywindow_globals.color_clipper = other;
        Brush_clipperColourChanged();
        SceneChangeNotify();
 }
-typedef FreeCaller1<const Vector3&, ClipperColour_set> ClipperColourSetCaller;
+typedef FreeCaller<void(const Vector3&), ClipperColour_set> ClipperColourSetCaller;
 
 void TextureBrowserColour_get( Vector3& other ){
        other = TextureBrowser_getBackgroundColour( GlobalTextureBrowser() );
 }
-typedef FreeCaller1<Vector3&, TextureBrowserColour_get> TextureBrowserColourGetCaller;
+typedef FreeCaller<void(Vector3&), TextureBrowserColour_get> TextureBrowserColourGetCaller;
 
 void TextureBrowserColour_set( const Vector3& other ){
        TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), other );
 }
-typedef FreeCaller1<const Vector3&, TextureBrowserColour_set> TextureBrowserColourSetCaller;
+typedef FreeCaller<void(const Vector3&), TextureBrowserColour_set> TextureBrowserColourSetCaller;
 
 
 class ColoursMenu
@@ -887,7 +1022,7 @@ ColoursMenu g_ColoursMenu;
 
 ui::MenuItem create_colours_menu(){
        auto colours_menu_item = new_sub_menu_item_with_mnemonic( "Colors" );
-       auto menu_in_menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( colours_menu_item ) ));
+       auto menu_in_menu = ui::Menu::from( gtk_menu_item_get_submenu( colours_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu_in_menu );
        }
@@ -999,24 +1134,24 @@ template<bool( *BoolFunction ) ( )>
 class BoolFunctionExport
 {
 public:
-static void apply( const BoolImportCallback& importCallback ){
+static void apply( const Callback<void(bool)> & importCallback ){
        importCallback( BoolFunction() );
 }
 };
 
-typedef FreeCaller1<const BoolImportCallback&, &BoolFunctionExport<EdgeMode>::apply> EdgeModeApplyCaller;
+typedef FreeCaller<void(const Callback<void(bool)> &), &BoolFunctionExport<EdgeMode>::apply> EdgeModeApplyCaller;
 EdgeModeApplyCaller g_edgeMode_button_caller;
-BoolExportCallback g_edgeMode_button_callback( g_edgeMode_button_caller );
+Callback<void(const Callback<void(bool)> &)> g_edgeMode_button_callback( g_edgeMode_button_caller );
 ToggleItem g_edgeMode_button( g_edgeMode_button_callback );
 
-typedef FreeCaller1<const BoolImportCallback&, &BoolFunctionExport<VertexMode>::apply> VertexModeApplyCaller;
+typedef FreeCaller<void(const Callback<void(bool)> &), &BoolFunctionExport<VertexMode>::apply> VertexModeApplyCaller;
 VertexModeApplyCaller g_vertexMode_button_caller;
-BoolExportCallback g_vertexMode_button_callback( g_vertexMode_button_caller );
+Callback<void(const Callback<void(bool)> &)> g_vertexMode_button_callback( g_vertexMode_button_caller );
 ToggleItem g_vertexMode_button( g_vertexMode_button_callback );
 
-typedef FreeCaller1<const BoolImportCallback&, &BoolFunctionExport<FaceMode>::apply> FaceModeApplyCaller;
+typedef FreeCaller<void(const Callback<void(bool)> &), &BoolFunctionExport<FaceMode>::apply> FaceModeApplyCaller;
 FaceModeApplyCaller g_faceMode_button_caller;
-BoolExportCallback g_faceMode_button_callback( g_faceMode_button_caller );
+Callback<void(const Callback<void(bool)> &)> g_faceMode_button_callback( g_faceMode_button_caller );
 ToggleItem g_faceMode_button( g_faceMode_button_callback );
 
 void ComponentModeChanged(){
@@ -1290,44 +1425,44 @@ void Selection_NudgeRight(){
 }
 
 
-void TranslateToolExport( const BoolImportCallback& importCallback ){
+void TranslateToolExport( const Callback<void(bool)> & importCallback ){
        importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eTranslate );
 }
 
-void RotateToolExport( const BoolImportCallback& importCallback ){
+void RotateToolExport( const Callback<void(bool)> & importCallback ){
        importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eRotate );
 }
 
-void ScaleToolExport( const BoolImportCallback& importCallback ){
+void ScaleToolExport( const Callback<void(bool)> & importCallback ){
        importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eScale );
 }
 
-void DragToolExport( const BoolImportCallback& importCallback ){
+void DragToolExport( const Callback<void(bool)> & importCallback ){
        importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag );
 }
 
-void ClipperToolExport( const BoolImportCallback& importCallback ){
+void ClipperToolExport( const Callback<void(bool)> & importCallback ){
        importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip );
 }
 
-FreeCaller1<const BoolImportCallback&, TranslateToolExport> g_translatemode_button_caller;
-BoolExportCallback g_translatemode_button_callback( g_translatemode_button_caller );
+FreeCaller<void(const Callback<void(bool)> &), TranslateToolExport> g_translatemode_button_caller;
+Callback<void(const Callback<void(bool)> &)> g_translatemode_button_callback( g_translatemode_button_caller );
 ToggleItem g_translatemode_button( g_translatemode_button_callback );
 
-FreeCaller1<const BoolImportCallback&, RotateToolExport> g_rotatemode_button_caller;
-BoolExportCallback g_rotatemode_button_callback( g_rotatemode_button_caller );
+FreeCaller<void(const Callback<void(bool)> &), RotateToolExport> g_rotatemode_button_caller;
+Callback<void(const Callback<void(bool)> &)> g_rotatemode_button_callback( g_rotatemode_button_caller );
 ToggleItem g_rotatemode_button( g_rotatemode_button_callback );
 
-FreeCaller1<const BoolImportCallback&, ScaleToolExport> g_scalemode_button_caller;
-BoolExportCallback g_scalemode_button_callback( g_scalemode_button_caller );
+FreeCaller<void(const Callback<void(bool)> &), ScaleToolExport> g_scalemode_button_caller;
+Callback<void(const Callback<void(bool)> &)> g_scalemode_button_callback( g_scalemode_button_caller );
 ToggleItem g_scalemode_button( g_scalemode_button_callback );
 
-FreeCaller1<const BoolImportCallback&, DragToolExport> g_dragmode_button_caller;
-BoolExportCallback g_dragmode_button_callback( g_dragmode_button_caller );
+FreeCaller<void(const Callback<void(bool)> &), DragToolExport> g_dragmode_button_caller;
+Callback<void(const Callback<void(bool)> &)> g_dragmode_button_callback( g_dragmode_button_caller );
 ToggleItem g_dragmode_button( g_dragmode_button_callback );
 
-FreeCaller1<const BoolImportCallback&, ClipperToolExport> g_clipper_button_caller;
-BoolExportCallback g_clipper_button_callback( g_clipper_button_caller );
+FreeCaller<void(const Callback<void(bool)> &), ClipperToolExport> g_clipper_button_caller;
+Callback<void(const Callback<void(bool)> &)> g_clipper_button_callback( g_clipper_button_caller );
 ToggleItem g_clipper_button( g_clipper_button_callback );
 
 void ToolChanged(){
@@ -1770,17 +1905,17 @@ void ClipperChangeNotify(){
 }
 
 
-LatchedInt g_Layout_viewStyle( 0, "Window Layout" );
-LatchedBool g_Layout_enableDetachableMenus( true, "Detachable Menus" );
-LatchedBool g_Layout_enablePatchToolbar( true, "Patch Toolbar" );
-LatchedBool g_Layout_enablePluginToolbar( true, "Plugin Toolbar" );
+LatchedValue<int> g_Layout_viewStyle( 0, "Window Layout" );
+LatchedValue<bool> g_Layout_enableDetachableMenus( true, "Detachable Menus" );
+LatchedValue<bool> g_Layout_enablePatchToolbar( true, "Patch Toolbar" );
+LatchedValue<bool> g_Layout_enablePluginToolbar( true, "Plugin Toolbar" );
 
 
 
 ui::MenuItem create_file_menu(){
        // File menu
        auto file_menu_item = new_sub_menu_item_with_mnemonic( "_File" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( file_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( file_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -1820,7 +1955,7 @@ ui::MenuItem create_file_menu(){
 ui::MenuItem create_edit_menu(){
        // Edit menu
        auto edit_menu_item = new_sub_menu_item_with_mnemonic( "_Edit" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( edit_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( edit_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -1877,7 +2012,7 @@ ui::Widget g_toggle_entitylist_item{ui::null};
 ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){
        // View menu
        auto view_menu_item = new_sub_menu_item_with_mnemonic( "Vie_w" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( view_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( view_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -1991,7 +2126,7 @@ ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){
 ui::MenuItem create_selection_menu(){
        // Selection menu
        auto selection_menu_item = new_sub_menu_item_with_mnemonic( "M_odify" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( selection_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( selection_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -2046,7 +2181,7 @@ ui::MenuItem create_selection_menu(){
 ui::MenuItem create_bsp_menu(){
        // BSP menu
        auto bsp_menu_item = new_sub_menu_item_with_mnemonic( "_Build" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( bsp_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( bsp_menu_item ) );
 
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
@@ -2066,7 +2201,7 @@ ui::MenuItem create_bsp_menu(){
 ui::MenuItem create_grid_menu(){
        // Grid menu
        auto grid_menu_item = new_sub_menu_item_with_mnemonic( "_Grid" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( grid_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( grid_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -2079,28 +2214,28 @@ ui::MenuItem create_grid_menu(){
 ui::MenuItem create_misc_menu(){
        // Misc menu
        auto misc_menu_item = new_sub_menu_item_with_mnemonic( "M_isc" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( misc_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( misc_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
 
 #if 0
-       create_menu_item_with_mnemonic( menu, "_Benchmark", FreeCaller<GlobalCamera_Benchmark>() );
+       create_menu_item_with_mnemonic( menu, "_Benchmark", makeCallbackF(GlobalCamera_Benchmark) );
 #endif
     menu.add(create_colours_menu());
 
        create_menu_item_with_mnemonic( menu, "Find brush...", "FindBrush" );
        create_menu_item_with_mnemonic( menu, "Map Info...", "MapInfo" );
        // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394
-//  create_menu_item_with_mnemonic(menu, "_Print XY View", FreeCaller<WXY_Print>());
-       create_menu_item_with_mnemonic( menu, "_Background select", FreeCaller<WXY_BackgroundSelect>() );
+//  create_menu_item_with_mnemonic(menu, "_Print XY View", FreeCaller<void(), WXY_Print>());
+       create_menu_item_with_mnemonic( menu, "_Background select", makeCallbackF(WXY_BackgroundSelect) );
        return misc_menu_item;
 }
 
 ui::MenuItem create_entity_menu(){
        // Brush menu
        auto entity_menu_item = new_sub_menu_item_with_mnemonic( "E_ntity" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( entity_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( entity_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -2113,7 +2248,7 @@ ui::MenuItem create_entity_menu(){
 ui::MenuItem create_brush_menu(){
        // Brush menu
        auto brush_menu_item = new_sub_menu_item_with_mnemonic( "B_rush" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( brush_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( brush_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -2126,7 +2261,7 @@ ui::MenuItem create_brush_menu(){
 ui::MenuItem create_patch_menu(){
        // Curve menu
        auto patch_menu_item = new_sub_menu_item_with_mnemonic( "_Curve" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( patch_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( patch_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -2139,7 +2274,7 @@ ui::MenuItem create_patch_menu(){
 ui::MenuItem create_help_menu(){
        // Help menu
        auto help_menu_item = new_sub_menu_item_with_mnemonic( "_Help" );
-       auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( help_menu_item ) ));
+       auto menu = ui::Menu::from( gtk_menu_item_get_submenu( help_menu_item ) );
        if ( g_Layout_enableDetachableMenus.m_value ) {
                menu_tearoff( menu );
        }
@@ -2150,15 +2285,15 @@ ui::MenuItem create_help_menu(){
        // it will take care of hooking the Sys_OpenURL calls etc.
        create_game_help_menu( menu );
 
-       create_menu_item_with_mnemonic( menu, "Bug report", FreeCaller<OpenBugReportURL>() );
-       create_menu_item_with_mnemonic( menu, "Shortcuts list", FreeCaller<DoCommandListDlg>() );
-       create_menu_item_with_mnemonic( menu, "_About", FreeCaller<DoAbout>() );
+       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) );
 
        return help_menu_item;
 }
 
 ui::MenuBar create_main_menu( MainFrame::EViewStyle style ){
-       auto menu_bar = ui::MenuBar(GTK_MENU_BAR( gtk_menu_bar_new() ));
+       auto menu_bar = ui::MenuBar::from( gtk_menu_bar_new() );
        menu_bar.show();
 
        menu_bar.add(create_file_menu());
@@ -2305,14 +2440,14 @@ void Manipulators_constructToolbar( ui::Toolbar toolbar ){
 }
 
 ui::Toolbar create_main_toolbar( MainFrame::EViewStyle style ){
-       auto toolbar = ui::Toolbar(GTK_TOOLBAR( gtk_toolbar_new() ));
+       auto toolbar = ui::Toolbar::from( gtk_toolbar_new() );
        gtk_orientable_set_orientation( GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL );
        gtk_toolbar_set_style( toolbar, GTK_TOOLBAR_ICONS );
 
        toolbar.show();
 
        auto space = [&]() {
-               auto btn = ui::ToolItem(gtk_separator_tool_item_new());
+               auto btn = ui::ToolItem::from(gtk_separator_tool_item_new());
                btn.show();
                toolbar.add(btn);
        };
@@ -2653,13 +2788,13 @@ void MainFrame::OnSleep(){
 
 
 ui::Window create_splash(){
-       ui::Window window = ui::Window( ui::window_type::TOP );
-       gtk_window_set_decorated( window, FALSE );
-       gtk_window_set_resizable( window, FALSE );
-       gtk_window_set_modal( window, TRUE );
+       auto window = ui::Window( ui::window_type::TOP );
+       gtk_window_set_decorated(window, false);
+       gtk_window_set_resizable(window, false);
+       gtk_window_set_modal(window, true);
        gtk_window_set_default_size( window, -1, -1 );
        gtk_window_set_position( window, GTK_WIN_POS_CENTER );
-       gtk_container_set_border_width( GTK_CONTAINER( window ), 0 );
+       gtk_container_set_border_width(window, 0);
 
        auto image = new_local_image( "splash.png" );
        image.show();
@@ -2971,7 +3106,7 @@ void MainFrame::Create(){
        SetActiveXY( m_pXYWnd );
 
        AddGridChangeCallback( SetGridStatusCaller( *this ) );
-       AddGridChangeCallback( ReferenceCaller<MainFrame, XY_UpdateAllWindows>( *this ) );
+       AddGridChangeCallback( ReferenceCaller<MainFrame, void(), XY_UpdateAllWindows>( *this ) );
 
        g_defaultToolMode = DragMode;
        g_defaultToolMode();
@@ -3126,26 +3261,22 @@ void Layout_constructPreferences( PreferencesPage& page ){
                page.appendRadioIcons(
                        "Window Layout",
                        STRING_ARRAY_RANGE( layouts ),
-                       LatchedIntImportCaller( g_Layout_viewStyle ),
-                       IntExportCaller( g_Layout_viewStyle.m_latched )
+                       make_property( g_Layout_viewStyle )
                        );
        }
        page.appendCheckBox(
                "", "Detachable Menus",
-               LatchedBoolImportCaller( g_Layout_enableDetachableMenus ),
-               BoolExportCaller( g_Layout_enableDetachableMenus.m_latched )
+               make_property( g_Layout_enableDetachableMenus )
                );
        if ( !string_empty( g_pGameDescription->getKeyValue( "no_patch" ) ) ) {
                page.appendCheckBox(
                        "", "Patch Toolbar",
-                       LatchedBoolImportCaller( g_Layout_enablePatchToolbar ),
-                       BoolExportCaller( g_Layout_enablePatchToolbar.m_latched )
+                       make_property( g_Layout_enablePatchToolbar )
                        );
        }
        page.appendCheckBox(
                "", "Plugin Toolbar",
-               LatchedBoolImportCaller( g_Layout_enablePluginToolbar ),
-               BoolExportCaller( g_Layout_enablePluginToolbar.m_latched )
+               make_property( g_Layout_enablePluginToolbar )
                );
 }
 
@@ -3155,7 +3286,7 @@ void Layout_constructPage( PreferenceGroup& group ){
 }
 
 void Layout_registerPreferencesPage(){
-       PreferencesDialog_addInterfacePage( FreeCaller1<PreferenceGroup&, Layout_constructPage>() );
+       PreferencesDialog_addInterfacePage( makeCallbackF(Layout_constructPage) );
 }
 
 
@@ -3163,75 +3294,75 @@ void Layout_registerPreferencesPage(){
 #include "stringio.h"
 
 void MainFrame_Construct(){
-       GlobalCommands_insert( "OpenManual", FreeCaller<OpenHelpURL>(), Accelerator( GDK_KEY_F1 ) );
-
-       GlobalCommands_insert( "Sleep", FreeCaller<thunk_OnSleep>(), Accelerator( 'P', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
-       GlobalCommands_insert( "NewMap", FreeCaller<NewMap>() );
-       GlobalCommands_insert( "OpenMap", FreeCaller<OpenMap>(), Accelerator( 'O', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "ImportMap", FreeCaller<ImportMap>() );
-       GlobalCommands_insert( "SaveMap", FreeCaller<SaveMap>(), Accelerator( 'S', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "SaveMapAs", FreeCaller<SaveMapAs>() );
-       GlobalCommands_insert( "ExportSelected", FreeCaller<ExportMap>() );
-       GlobalCommands_insert( "SaveRegion", FreeCaller<SaveRegion>() );
-       GlobalCommands_insert( "RefreshReferences", FreeCaller<VFS_Refresh>() );
-       GlobalCommands_insert( "ProjectSettings", FreeCaller<DoProjectSettings>() );
-       GlobalCommands_insert( "Exit", FreeCaller<Exit>() );
-
-       GlobalCommands_insert( "Undo", FreeCaller<Undo>(), Accelerator( 'Z', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "Redo", FreeCaller<Redo>(), Accelerator( 'Y', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "Copy", FreeCaller<Copy>(), Accelerator( 'C', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "Paste", FreeCaller<Paste>(), Accelerator( 'V', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "PasteToCamera", FreeCaller<PasteToCamera>(), Accelerator( 'V', (GdkModifierType)GDK_MOD1_MASK ) );
-       GlobalCommands_insert( "CloneSelection", FreeCaller<Selection_Clone>(), Accelerator( GDK_KEY_space ) );
-       GlobalCommands_insert( "CloneSelectionAndMakeUnique", FreeCaller<Selection_Clone_MakeUnique>(), Accelerator( GDK_KEY_space, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "DeleteSelection", FreeCaller<deleteSelection>(), Accelerator( GDK_KEY_BackSpace ) );
-       GlobalCommands_insert( "ParentSelection", FreeCaller<Scene_parentSelected>() );
-       GlobalCommands_insert( "UnSelectSelection", FreeCaller<Selection_Deselect>(), Accelerator( GDK_KEY_Escape ) );
-       GlobalCommands_insert( "InvertSelection", FreeCaller<Select_Invert>(), Accelerator( 'I' ) );
-       GlobalCommands_insert( "SelectInside", FreeCaller<Select_Inside>() );
-       GlobalCommands_insert( "SelectTouching", FreeCaller<Select_Touching>() );
-       GlobalCommands_insert( "ExpandSelectionToEntities", FreeCaller<Scene_ExpandSelectionToEntities>(), Accelerator( 'E', (GdkModifierType)( GDK_MOD1_MASK | GDK_CONTROL_MASK ) ) );
-       GlobalCommands_insert( "Preferences", FreeCaller<PreferencesDialog_showDialog>(), Accelerator( 'P' ) );
-
-       GlobalCommands_insert( "ToggleConsole", FreeCaller<Console_ToggleShow>(), Accelerator( 'O' ) );
-       GlobalCommands_insert( "ToggleEntityInspector", FreeCaller<EntityInspector_ToggleShow>(), Accelerator( 'N' ) );
-       GlobalCommands_insert( "EntityList", FreeCaller<EntityList_toggleShown>(), Accelerator( 'L' ) );
-
-       GlobalCommands_insert( "ShowHidden", FreeCaller<Select_ShowAllHidden>(), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "HideSelected", FreeCaller<HideSelected>(), Accelerator( 'H' ) );
-
-       GlobalToggles_insert( "DragVertices", FreeCaller<SelectVertexMode>(), ToggleItem::AddCallbackCaller( g_vertexMode_button ), Accelerator( 'V' ) );
-       GlobalToggles_insert( "DragEdges", FreeCaller<SelectEdgeMode>(), ToggleItem::AddCallbackCaller( g_edgeMode_button ), Accelerator( 'E' ) );
-       GlobalToggles_insert( "DragFaces", FreeCaller<SelectFaceMode>(), ToggleItem::AddCallbackCaller( g_faceMode_button ), Accelerator( 'F' ) );
-
-       GlobalCommands_insert( "MirrorSelectionX", FreeCaller<Selection_Flipx>() );
-       GlobalCommands_insert( "RotateSelectionX", FreeCaller<Selection_Rotatex>() );
-       GlobalCommands_insert( "MirrorSelectionY", FreeCaller<Selection_Flipy>() );
-       GlobalCommands_insert( "RotateSelectionY", FreeCaller<Selection_Rotatey>() );
-       GlobalCommands_insert( "MirrorSelectionZ", FreeCaller<Selection_Flipz>() );
-       GlobalCommands_insert( "RotateSelectionZ", FreeCaller<Selection_Rotatez>() );
-
-       GlobalCommands_insert( "ArbitraryRotation", FreeCaller<DoRotateDlg>() );
-       GlobalCommands_insert( "ArbitraryScale", FreeCaller<DoScaleDlg>() );
-
-       GlobalCommands_insert( "BuildMenuCustomize", FreeCaller<DoBuildMenu>() );
-
-       GlobalCommands_insert( "FindBrush", FreeCaller<DoFind>() );
-
-       GlobalCommands_insert( "MapInfo", FreeCaller<DoMapInfo>(), Accelerator( 'M' ) );
-
-
-       GlobalToggles_insert( "ToggleClipper", FreeCaller<ClipperMode>(), ToggleItem::AddCallbackCaller( g_clipper_button ), Accelerator( 'X' ) );
-
-       GlobalToggles_insert( "MouseTranslate", FreeCaller<TranslateMode>(), ToggleItem::AddCallbackCaller( g_translatemode_button ), Accelerator( 'W' ) );
-       GlobalToggles_insert( "MouseRotate", FreeCaller<RotateMode>(), ToggleItem::AddCallbackCaller( g_rotatemode_button ), Accelerator( 'R' ) );
-       GlobalToggles_insert( "MouseScale", FreeCaller<ScaleMode>(), ToggleItem::AddCallbackCaller( g_scalemode_button ) );
-       GlobalToggles_insert( "MouseDrag", FreeCaller<DragMode>(), ToggleItem::AddCallbackCaller( g_dragmode_button ), Accelerator( 'Q' ) );
-
-       GlobalCommands_insert( "ColorSchemeOriginal", FreeCaller<ColorScheme_Original>() );
-       GlobalCommands_insert( "ColorSchemeQER", FreeCaller<ColorScheme_QER>() );
-       GlobalCommands_insert( "ColorSchemeBlackAndGreen", FreeCaller<ColorScheme_Black>() );
-       GlobalCommands_insert( "ColorSchemeYdnar", FreeCaller<ColorScheme_Ydnar>() );
+       GlobalCommands_insert( "OpenManual", makeCallbackF(OpenHelpURL), Accelerator( GDK_KEY_F1 ) );
+
+       GlobalCommands_insert( "Sleep", makeCallbackF(thunk_OnSleep), Accelerator( 'P', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "NewMap", makeCallbackF(NewMap) );
+       GlobalCommands_insert( "OpenMap", makeCallbackF(OpenMap), Accelerator( 'O', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "ImportMap", makeCallbackF(ImportMap) );
+       GlobalCommands_insert( "SaveMap", makeCallbackF(SaveMap), Accelerator( 'S', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "SaveMapAs", makeCallbackF(SaveMapAs) );
+       GlobalCommands_insert( "ExportSelected", makeCallbackF(ExportMap) );
+       GlobalCommands_insert( "SaveRegion", makeCallbackF(SaveRegion) );
+       GlobalCommands_insert( "RefreshReferences", makeCallbackF(VFS_Refresh) );
+       GlobalCommands_insert( "ProjectSettings", makeCallbackF(DoProjectSettings) );
+       GlobalCommands_insert( "Exit", makeCallbackF(Exit) );
+
+       GlobalCommands_insert( "Undo", makeCallbackF(Undo), Accelerator( 'Z', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "Redo", makeCallbackF(Redo), Accelerator( 'Y', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "Copy", makeCallbackF(Copy), Accelerator( 'C', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "Paste", makeCallbackF(Paste), Accelerator( 'V', (GdkModifierType)GDK_CONTROL_MASK ) );
+       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( "ParentSelection", makeCallbackF(Scene_parentSelected) );
+       GlobalCommands_insert( "UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator( GDK_KEY_Escape ) );
+       GlobalCommands_insert( "InvertSelection", makeCallbackF(Select_Invert), Accelerator( 'I' ) );
+       GlobalCommands_insert( "SelectInside", makeCallbackF(Select_Inside) );
+       GlobalCommands_insert( "SelectTouching", makeCallbackF(Select_Touching) );
+       GlobalCommands_insert( "ExpandSelectionToEntities", makeCallbackF(Scene_ExpandSelectionToEntities), Accelerator( 'E', (GdkModifierType)( GDK_MOD1_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "Preferences", makeCallbackF(PreferencesDialog_showDialog), Accelerator( 'P' ) );
+
+       GlobalCommands_insert( "ToggleConsole", makeCallbackF(Console_ToggleShow), Accelerator( 'O' ) );
+       GlobalCommands_insert( "ToggleEntityInspector", makeCallbackF(EntityInspector_ToggleShow), Accelerator( 'N' ) );
+       GlobalCommands_insert( "EntityList", makeCallbackF(EntityList_toggleShown), Accelerator( 'L' ) );
+
+       GlobalCommands_insert( "ShowHidden", makeCallbackF(Select_ShowAllHidden), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "HideSelected", makeCallbackF(HideSelected), Accelerator( 'H' ) );
+
+       GlobalToggles_insert( "DragVertices", makeCallbackF(SelectVertexMode), ToggleItem::AddCallbackCaller( g_vertexMode_button ), Accelerator( 'V' ) );
+       GlobalToggles_insert( "DragEdges", makeCallbackF(SelectEdgeMode), ToggleItem::AddCallbackCaller( g_edgeMode_button ), Accelerator( 'E' ) );
+       GlobalToggles_insert( "DragFaces", makeCallbackF(SelectFaceMode), ToggleItem::AddCallbackCaller( g_faceMode_button ), Accelerator( 'F' ) );
+
+       GlobalCommands_insert( "MirrorSelectionX", makeCallbackF(Selection_Flipx) );
+       GlobalCommands_insert( "RotateSelectionX", makeCallbackF(Selection_Rotatex) );
+       GlobalCommands_insert( "MirrorSelectionY", makeCallbackF(Selection_Flipy) );
+       GlobalCommands_insert( "RotateSelectionY", makeCallbackF(Selection_Rotatey) );
+       GlobalCommands_insert( "MirrorSelectionZ", makeCallbackF(Selection_Flipz) );
+       GlobalCommands_insert( "RotateSelectionZ", makeCallbackF(Selection_Rotatez) );
+
+       GlobalCommands_insert( "ArbitraryRotation", makeCallbackF(DoRotateDlg) );
+       GlobalCommands_insert( "ArbitraryScale", makeCallbackF(DoScaleDlg) );
+
+       GlobalCommands_insert( "BuildMenuCustomize", makeCallbackF(DoBuildMenu) );
+
+       GlobalCommands_insert( "FindBrush", makeCallbackF(DoFind) );
+
+       GlobalCommands_insert( "MapInfo", makeCallbackF(DoMapInfo), Accelerator( 'M' ) );
+
+
+       GlobalToggles_insert( "ToggleClipper", makeCallbackF(ClipperMode), ToggleItem::AddCallbackCaller( g_clipper_button ), Accelerator( 'X' ) );
+
+       GlobalToggles_insert( "MouseTranslate", makeCallbackF(TranslateMode), ToggleItem::AddCallbackCaller( g_translatemode_button ), Accelerator( 'W' ) );
+       GlobalToggles_insert( "MouseRotate", makeCallbackF(RotateMode), ToggleItem::AddCallbackCaller( g_rotatemode_button ), Accelerator( 'R' ) );
+       GlobalToggles_insert( "MouseScale", makeCallbackF(ScaleMode), ToggleItem::AddCallbackCaller( g_scalemode_button ) );
+       GlobalToggles_insert( "MouseDrag", makeCallbackF(DragMode), ToggleItem::AddCallbackCaller( g_dragmode_button ), Accelerator( 'Q' ) );
+
+       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( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) );
        GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) );
        GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) );
@@ -3248,60 +3379,60 @@ void MainFrame_Construct(){
        GlobalCommands_insert( "ChooseOrthoViewNameColor", makeCallback( g_ColoursMenu.m_viewname ) );
 
 
-       GlobalCommands_insert( "CSGSubtract", FreeCaller<CSG_Subtract>(), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "CSGMerge", FreeCaller<CSG_Merge>(), Accelerator( 'U', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "CSGHollow", FreeCaller<CSG_MakeHollow>() );
+       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) );
 
        Grid_registerCommands();
 
-       GlobalCommands_insert( "SnapToGrid", FreeCaller<Selection_SnapToGrid>(), Accelerator( 'G', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "SnapToGrid", makeCallbackF(Selection_SnapToGrid), Accelerator( 'G', (GdkModifierType)GDK_CONTROL_MASK ) );
 
-       GlobalCommands_insert( "SelectAllOfType", FreeCaller<Select_AllOfType>(), Accelerator( 'A', (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "SelectAllOfType", makeCallbackF(Select_AllOfType), Accelerator( 'A', (GdkModifierType)GDK_SHIFT_MASK ) );
 
-       GlobalCommands_insert( "TexRotateClock", FreeCaller<Texdef_RotateClockwise>(), Accelerator( GDK_KEY_Next, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "TexRotateCounter", FreeCaller<Texdef_RotateAntiClockwise>(), Accelerator( GDK_KEY_Prior, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "TexScaleUp", FreeCaller<Texdef_ScaleUp>(), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "TexScaleDown", FreeCaller<Texdef_ScaleDown>(), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "TexScaleLeft", FreeCaller<Texdef_ScaleLeft>(), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "TexScaleRight", FreeCaller<Texdef_ScaleRight>(), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "TexShiftUp", FreeCaller<Texdef_ShiftUp>(), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "TexShiftDown", FreeCaller<Texdef_ShiftDown>(), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "TexShiftLeft", FreeCaller<Texdef_ShiftLeft>(), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "TexShiftRight", FreeCaller<Texdef_ShiftRight>(), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "TexRotateClock", makeCallbackF(Texdef_RotateClockwise), Accelerator( GDK_KEY_Next, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "TexRotateCounter", makeCallbackF(Texdef_RotateAntiClockwise), Accelerator( GDK_KEY_Prior, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "TexScaleUp", makeCallbackF(Texdef_ScaleUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "TexScaleDown", makeCallbackF(Texdef_ScaleDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "TexScaleLeft", makeCallbackF(Texdef_ScaleLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "TexScaleRight", makeCallbackF(Texdef_ScaleRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "TexShiftUp", makeCallbackF(Texdef_ShiftUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "TexShiftDown", makeCallbackF(Texdef_ShiftDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "TexShiftLeft", makeCallbackF(Texdef_ShiftLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "TexShiftRight", makeCallbackF(Texdef_ShiftRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_SHIFT_MASK ) );
 
-       GlobalCommands_insert( "MoveSelectionDOWN", FreeCaller<Selection_MoveDown>(), Accelerator( GDK_KEY_KP_Subtract ) );
-       GlobalCommands_insert( "MoveSelectionUP", FreeCaller<Selection_MoveUp>(), Accelerator( GDK_KEY_KP_Add ) );
+       GlobalCommands_insert( "MoveSelectionDOWN", makeCallbackF(Selection_MoveDown), Accelerator( GDK_KEY_KP_Subtract ) );
+       GlobalCommands_insert( "MoveSelectionUP", makeCallbackF(Selection_MoveUp), Accelerator( GDK_KEY_KP_Add ) );
 
-       GlobalCommands_insert( "SelectNudgeLeft", FreeCaller<Selection_NudgeLeft>(), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_MOD1_MASK ) );
-       GlobalCommands_insert( "SelectNudgeRight", FreeCaller<Selection_NudgeRight>(), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_MOD1_MASK ) );
-       GlobalCommands_insert( "SelectNudgeUp", FreeCaller<Selection_NudgeUp>(), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_MOD1_MASK ) );
-       GlobalCommands_insert( "SelectNudgeDown", FreeCaller<Selection_NudgeDown>(), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_MOD1_MASK ) );
+       GlobalCommands_insert( "SelectNudgeLeft", makeCallbackF(Selection_NudgeLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_MOD1_MASK ) );
+       GlobalCommands_insert( "SelectNudgeRight", makeCallbackF(Selection_NudgeRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_MOD1_MASK ) );
+       GlobalCommands_insert( "SelectNudgeUp", makeCallbackF(Selection_NudgeUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_MOD1_MASK ) );
+       GlobalCommands_insert( "SelectNudgeDown", makeCallbackF(Selection_NudgeDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_MOD1_MASK ) );
 
        Patch_registerCommands();
        XYShow_registerCommands();
 
-       typedef FreeCaller1<const Selectable&, ComponentMode_SelectionChanged> ComponentModeSelectionChangedCaller;
+       typedef FreeCaller<void(const Selectable&), ComponentMode_SelectionChanged> ComponentModeSelectionChangedCaller;
        GlobalSelectionSystem().addSelectionChangeCallback( ComponentModeSelectionChangedCaller() );
 
-       GlobalPreferenceSystem().registerPreference( "DetachableMenus", BoolImportStringCaller( g_Layout_enableDetachableMenus.m_latched ), BoolExportStringCaller( g_Layout_enableDetachableMenus.m_latched ) );
-       GlobalPreferenceSystem().registerPreference( "PatchToolBar", BoolImportStringCaller( g_Layout_enablePatchToolbar.m_latched ), BoolExportStringCaller( g_Layout_enablePatchToolbar.m_latched ) );
-       GlobalPreferenceSystem().registerPreference( "PluginToolBar", BoolImportStringCaller( g_Layout_enablePluginToolbar.m_latched ), BoolExportStringCaller( g_Layout_enablePluginToolbar.m_latched ) );
-       GlobalPreferenceSystem().registerPreference( "QE4StyleWindows", IntImportStringCaller( g_Layout_viewStyle.m_latched ), IntExportStringCaller( g_Layout_viewStyle.m_latched ) );
-       GlobalPreferenceSystem().registerPreference( "XYHeight", IntImportStringCaller( g_layout_globals.nXYHeight ), IntExportStringCaller( g_layout_globals.nXYHeight ) );
-       GlobalPreferenceSystem().registerPreference( "XYWidth", IntImportStringCaller( g_layout_globals.nXYWidth ), IntExportStringCaller( g_layout_globals.nXYWidth ) );
-       GlobalPreferenceSystem().registerPreference( "CamWidth", IntImportStringCaller( g_layout_globals.nCamWidth ), IntExportStringCaller( g_layout_globals.nCamWidth ) );
-       GlobalPreferenceSystem().registerPreference( "CamHeight", IntImportStringCaller( g_layout_globals.nCamHeight ), IntExportStringCaller( g_layout_globals.nCamHeight ) );
-
-       GlobalPreferenceSystem().registerPreference( "State", IntImportStringCaller( g_layout_globals.nState ), IntExportStringCaller( g_layout_globals.nState ) );
-       GlobalPreferenceSystem().registerPreference( "PositionX", IntImportStringCaller( g_layout_globals.m_position.x ), IntExportStringCaller( g_layout_globals.m_position.x ) );
-       GlobalPreferenceSystem().registerPreference( "PositionY", IntImportStringCaller( g_layout_globals.m_position.y ), IntExportStringCaller( g_layout_globals.m_position.y ) );
-       GlobalPreferenceSystem().registerPreference( "Width", IntImportStringCaller( g_layout_globals.m_position.w ), IntExportStringCaller( g_layout_globals.m_position.w ) );
-       GlobalPreferenceSystem().registerPreference( "Height", IntImportStringCaller( g_layout_globals.m_position.h ), IntExportStringCaller( g_layout_globals.m_position.h ) );
-
-       GlobalPreferenceSystem().registerPreference( "CamWnd", WindowPositionTrackerImportStringCaller( g_posCamWnd ), WindowPositionTrackerExportStringCaller( g_posCamWnd ) );
-       GlobalPreferenceSystem().registerPreference( "XYWnd", WindowPositionTrackerImportStringCaller( g_posXYWnd ), WindowPositionTrackerExportStringCaller( g_posXYWnd ) );
-       GlobalPreferenceSystem().registerPreference( "YZWnd", WindowPositionTrackerImportStringCaller( g_posYZWnd ), WindowPositionTrackerExportStringCaller( g_posYZWnd ) );
-       GlobalPreferenceSystem().registerPreference( "XZWnd", WindowPositionTrackerImportStringCaller( g_posXZWnd ), WindowPositionTrackerExportStringCaller( g_posXZWnd ) );
+       GlobalPreferenceSystem().registerPreference( "DetachableMenus", make_property_string( g_Layout_enableDetachableMenus.m_latched ) );
+       GlobalPreferenceSystem().registerPreference( "PatchToolBar", make_property_string( g_Layout_enablePatchToolbar.m_latched ) );
+       GlobalPreferenceSystem().registerPreference( "PluginToolBar", make_property_string( g_Layout_enablePluginToolbar.m_latched ) );
+       GlobalPreferenceSystem().registerPreference( "QE4StyleWindows", make_property_string( g_Layout_viewStyle.m_latched ) );
+       GlobalPreferenceSystem().registerPreference( "XYHeight", make_property_string( g_layout_globals.nXYHeight ) );
+       GlobalPreferenceSystem().registerPreference( "XYWidth", make_property_string( g_layout_globals.nXYWidth ) );
+       GlobalPreferenceSystem().registerPreference( "CamWidth", make_property_string( g_layout_globals.nCamWidth ) );
+       GlobalPreferenceSystem().registerPreference( "CamHeight", make_property_string( g_layout_globals.nCamHeight ) );
+
+       GlobalPreferenceSystem().registerPreference( "State", make_property_string( g_layout_globals.nState ) );
+       GlobalPreferenceSystem().registerPreference( "PositionX", make_property_string( g_layout_globals.m_position.x ) );
+       GlobalPreferenceSystem().registerPreference( "PositionY", make_property_string( g_layout_globals.m_position.y ) );
+       GlobalPreferenceSystem().registerPreference( "Width", make_property_string( g_layout_globals.m_position.w ) );
+       GlobalPreferenceSystem().registerPreference( "Height", make_property_string( g_layout_globals.m_position.h ) );
+
+       GlobalPreferenceSystem().registerPreference( "CamWnd", make_property<WindowPositionTracker_String>(g_posCamWnd) );
+       GlobalPreferenceSystem().registerPreference( "XYWnd", make_property<WindowPositionTracker_String>(g_posXYWnd) );
+       GlobalPreferenceSystem().registerPreference( "YZWnd", make_property<WindowPositionTracker_String>(g_posYZWnd) );
+       GlobalPreferenceSystem().registerPreference( "XZWnd", make_property<WindowPositionTracker_String>(g_posXZWnd) );
 
        {
                const char* ENGINEPATH_ATTRIBUTE =
@@ -3320,7 +3451,15 @@ void MainFrame_Construct(){
                g_strEnginePath = path.c_str();
        }
 
-       GlobalPreferenceSystem().registerPreference( "EnginePath", CopiedStringImportStringCaller( g_strEnginePath ), CopiedStringExportStringCaller( g_strEnginePath ) );
+       GlobalPreferenceSystem().registerPreference( "EnginePath", make_property_string( g_strEnginePath ) );
+
+       GlobalPreferenceSystem().registerPreference( "DisableEnginePath", make_property_string( g_disableEnginePath ) );
+       GlobalPreferenceSystem().registerPreference( "DisableHomePath", make_property_string( g_disableHomePath ) );
+
+       for ( int i = 0; i < g_pakPathCount; i++ ) {
+               std::string label = "PakPath" + std::to_string(i);
+               GlobalPreferenceSystem().registerPreference( label.c_str(), make_property_string( g_strPakPath[i] ) );
+       }
 
        g_Layout_viewStyle.useLatched();
        g_Layout_enableDetachableMenus.useLatched();
@@ -3330,8 +3469,8 @@ void MainFrame_Construct(){
        Layout_registerPreferencesPage();
        Paths_registerPreferencesPage();
 
-       g_brushCount.setCountChangedCallback( FreeCaller<QE_brushCountChanged>() );
-       g_entityCount.setCountChangedCallback( FreeCaller<QE_entityCountChanged>() );
+       g_brushCount.setCountChangedCallback( makeCallbackF(QE_brushCountChanged) );
+       g_entityCount.setCountChangedCallback( makeCallbackF(QE_entityCountChanged) );
        GlobalEntityCreator().setCounter( &g_entityCount );
 
        GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated;
@@ -3344,13 +3483,13 @@ void MainFrame_Destroy(){
        GlobalEntityClassManager().detach( g_WorldspawnColourEntityClassObserver );
 
        GlobalEntityCreator().setCounter( 0 );
-       g_entityCount.setCountChangedCallback( Callback() );
-       g_brushCount.setCountChangedCallback( Callback() );
+       g_entityCount.setCountChangedCallback( Callback<void()>() );
+       g_brushCount.setCountChangedCallback( Callback<void()>() );
 }
 
 
 void GLWindow_Construct(){
-       GlobalPreferenceSystem().registerPreference( "MouseButtons", IntImportStringCaller( g_glwindow_globals.m_nMouseType ), IntExportStringCaller( g_glwindow_globals.m_nMouseType ) );
+       GlobalPreferenceSystem().registerPreference( "MouseButtons", make_property_string( g_glwindow_globals.m_nMouseType ) );
 }
 
 void GLWindow_Destroy(){