From cba5583d23500efab17b84b508d109433365191c Mon Sep 17 00:00:00 2001 From: Garux Date: Wed, 2 Aug 2017 09:24:32 +0300 Subject: [PATCH] Radiant: binds... * m1 + shift drag: snapped modes of manipulators: scale free: scale two axes synchronously * m2 in entities creation menu: change classname; ctrl + m2: change classname, don't close menu * ctrl + m1 in entities creation menu: create entity, don't close menu (+offset every next entity by 8u or gridsize, if > 8) misc... * fix: laggy selectors, manipulators in mlook mode * scale free->snapped mode: constrain to two axes, most perpendicular to view direction (i.e. works for two axes in 3d too) * scale free->snapped mode: use min move delta for scale (was max = hard to scale down); fix ZY projection case * fix: pointfile was considered as shown, when trying to load missing one * entity inspector->EntityProperties treeview: Tab keypress = focus Key field * 2x2 layout: allow gtk to handle separators positions; fixes: unmaximize wnd, maximize = horizontal separators > center fixes: unmaximize wnd = not updated views glwidget positions on some systems * fix: paint selector, selecting occluded faces * camera->field of view option * wider Texture Gamma preference range * wad games->texbro treeview: do not group names, using underscore; fixes crash on loading parent; fixes mess if path contains underscore * fix: do not quit freelook on autosaving * entity creation menu has ability to be 'tearoff' * wad games: fix TextureBrowser_ShowDirectory crash on loading common dir (can cfg to load .wad), on loading containing dir (do nothing) * wad games: fix crash on selecting a shader (not a plain texture) in tex bro * wad games: more reliable filterbar texturing defaults * shader for 'caulk new brushes' and 'clipper uses caulk' options is optional via 'shader_caulk' option in .game --- contrib/bobtoolz/DPatch.cpp | 2 +- libs/gtkutil/paned.cpp | 33 +++++++----- libs/gtkutil/paned.h | 1 - radiant/camwindow.cpp | 33 ++++++++++-- radiant/csg.cpp | 21 +++----- radiant/entity.cpp | 16 +++--- radiant/entityinspector.cpp | 21 ++++++-- radiant/filterbar.cpp | 59 ++++++++++++++------- radiant/filterbar.h | 7 ++- radiant/mainframe.cpp | 9 +++- radiant/points.cpp | 6 ++- radiant/selection.cpp | 44 ++++++++++------ radiant/textures.cpp | 2 +- radiant/texwindow.cpp | 57 +++++++++++++++----- radiant/xywindow.cpp | 102 +++++++++++++++++++++++++----------- 15 files changed, 275 insertions(+), 138 deletions(-) diff --git a/contrib/bobtoolz/DPatch.cpp b/contrib/bobtoolz/DPatch.cpp index 06b0327b..71bad58a 100644 --- a/contrib/bobtoolz/DPatch.cpp +++ b/contrib/bobtoolz/DPatch.cpp @@ -302,7 +302,7 @@ DPatch* DPatch::MergePatches( patch_merge_t merge_info, DPatch *p1, DPatch *p2 ) int newHeight = p1->height + p2->height - 1; if ( newHeight > MAX_PATCH_HEIGHT ) { - return false; + return 0; } DPatch* newPatch = new DPatch(); diff --git a/libs/gtkutil/paned.cpp b/libs/gtkutil/paned.cpp index a78966e7..458f7597 100644 --- a/libs/gtkutil/paned.cpp +++ b/libs/gtkutil/paned.cpp @@ -26,7 +26,7 @@ #include "frame.h" - +#if 0 class PanedState { public: @@ -60,37 +60,44 @@ gboolean paned_position( GtkWidget* widget, gpointer dummy, PanedState* paned ){ PanedState g_hpaned = { 0.5f, -1, }; PanedState g_vpaned1 = { 0.5f, -1, }; PanedState g_vpaned2 = { 0.5f, -1, }; +#endif GtkWidget* create_split_views( GtkWidget* topleft, GtkWidget* botleft, GtkWidget* topright, GtkWidget* botright, GtkWidget*& vsplit1, GtkWidget*& vsplit2 ){ GtkHPaned* hsplit = GTK_HPANED( gtk_hpaned_new() ); gtk_widget_show( GTK_WIDGET( hsplit ) ); - g_signal_connect( G_OBJECT( hsplit ), "size_allocate", G_CALLBACK( hpaned_allocate ), &g_hpaned ); - g_signal_connect( G_OBJECT( hsplit ), "notify::position", G_CALLBACK( paned_position ), &g_hpaned ); + //g_signal_connect( G_OBJECT( hsplit ), "size_allocate", G_CALLBACK( hpaned_allocate ), &g_hpaned ); + //g_signal_connect( G_OBJECT( hsplit ), "notify::position", G_CALLBACK( paned_position ), &g_hpaned ); { GtkVPaned* vsplit = GTK_VPANED( gtk_vpaned_new() ); vsplit1 = GTK_WIDGET( vsplit ); - gtk_paned_add1( GTK_PANED( hsplit ), GTK_WIDGET( vsplit ) ); + //gtk_paned_add1( GTK_PANED( hsplit ), GTK_WIDGET( vsplit ) ); + gtk_paned_pack1( GTK_PANED( hsplit ), GTK_WIDGET( vsplit ), TRUE, TRUE ); gtk_widget_show( GTK_WIDGET( vsplit ) ); - g_signal_connect( G_OBJECT( vsplit ), "size_allocate", G_CALLBACK( vpaned_allocate ), &g_vpaned1 ); - g_signal_connect( G_OBJECT( vsplit ), "notify::position", G_CALLBACK( paned_position ), &g_vpaned1 ); + //g_signal_connect( G_OBJECT( vsplit ), "size_allocate", G_CALLBACK( vpaned_allocate ), &g_vpaned1 ); + //g_signal_connect( G_OBJECT( vsplit ), "notify::position", G_CALLBACK( paned_position ), &g_vpaned1 ); - gtk_paned_add1( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( topleft ) ) ); - gtk_paned_add2( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( botleft ) ) ); + //gtk_paned_add1( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( topleft ) ) ); + //gtk_paned_add2( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( botleft ) ) ); + gtk_paned_pack1( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( topleft ) ), TRUE, TRUE ); + gtk_paned_pack2( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( botleft ) ), TRUE, TRUE ); } { GtkVPaned* vsplit = GTK_VPANED( gtk_vpaned_new() ); vsplit2 = GTK_WIDGET( vsplit ); - gtk_paned_add2( GTK_PANED( hsplit ), GTK_WIDGET( vsplit ) ); + //gtk_paned_add2( GTK_PANED( hsplit ), GTK_WIDGET( vsplit ) ); + gtk_paned_pack2( GTK_PANED( hsplit ), GTK_WIDGET( vsplit ), TRUE, TRUE ); gtk_widget_show( GTK_WIDGET( vsplit ) ); - g_signal_connect( G_OBJECT( vsplit ), "size_allocate", G_CALLBACK( vpaned_allocate ), &g_vpaned2 ); - g_signal_connect( G_OBJECT( vsplit ), "notify::position", G_CALLBACK( paned_position ), &g_vpaned2 ); + //g_signal_connect( G_OBJECT( vsplit ), "size_allocate", G_CALLBACK( vpaned_allocate ), &g_vpaned2 ); + //g_signal_connect( G_OBJECT( vsplit ), "notify::position", G_CALLBACK( paned_position ), &g_vpaned2 ); - gtk_paned_add1( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( topright ) ) ); - gtk_paned_add2( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( botright ) ) ); + //gtk_paned_add1( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( topright ) ) ); + //gtk_paned_add2( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( botright ) ) ); + gtk_paned_pack1( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( topright ) ), TRUE, TRUE ); + gtk_paned_pack2( GTK_PANED( vsplit ), GTK_WIDGET( create_framed_widget( botright ) ), TRUE, TRUE ); } return GTK_WIDGET( hsplit ); } diff --git a/libs/gtkutil/paned.h b/libs/gtkutil/paned.h index 2c95be41..323a58aa 100644 --- a/libs/gtkutil/paned.h +++ b/libs/gtkutil/paned.h @@ -23,7 +23,6 @@ #define INCLUDED_GTKUTIL_PANED_H typedef struct _GtkWidget GtkWidget; -typedef struct _GtkHPaned GtkHPaned; GtkWidget* create_split_views( GtkWidget* topleft, GtkWidget* botleft, GtkWidget* topright, GtkWidget* botright, GtkWidget*& vsplit1, GtkWidget*& vsplit2 ); #endif diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index 54617155..ef7c5795 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -149,7 +149,7 @@ struct camera_t guint m_keymove_handler; - float fieldOfView; + static float fieldOfView; DeferredMotionDelta m_mouseMove; @@ -171,13 +171,13 @@ struct camera_t color( 0, 0, 0 ), movementflags( 0 ), m_keymove_handler( 0 ), - fieldOfView( 110.0f ), m_mouseMove( motionDelta, this ), m_view( view ), m_update( update ){ } }; +float camera_t::fieldOfView = 110.0f; camera_draw_mode camera_t::draw_mode = cd_texture; inline Matrix4 projection_for_camera( float near_z, float far_z, float fieldOfView, int width, int height ){ @@ -200,7 +200,7 @@ float Camera_getFarClipPlane( camera_t& camera ){ void Camera_updateProjection( camera_t& camera ){ float farClip = Camera_getFarClipPlane( camera ); - camera.projection = projection_for_camera( farClip / 4096.0f, farClip, camera.fieldOfView, camera.width, camera.height ); + camera.projection = projection_for_camera( farClip / 4096.0f, farClip, camera_t::fieldOfView, camera.width, camera.height ); camera.m_view->Construct( camera.projection, camera.modelview, camera.width, camera.height ); } @@ -703,6 +703,7 @@ XORRectangle m_XORRectangle; DeferredDraw m_deferredDraw; DeferredMotion m_deferred_motion; +DeferredMotion m_deferred_motion_freemove; guint m_selection_button_press_handler; guint m_selection_button_release_handler; @@ -937,11 +938,17 @@ gboolean selection_button_release_freemove( GtkWidget* widget, GdkEventButton* e } return FALSE; } - +#if 0 gboolean selection_motion_freemove( GtkWidget *widget, GdkEventMotion *event, WindowObserver* observer ){ observer->onMouseMotion( windowvector_for_widget_centre( widget ), modifiers_for_state( event->state ) ); return FALSE; } +#endif +void selection_motion_freemove( gdouble x, gdouble y, guint state, void* data ){ + //globalOutputStream() << "motion... "; + CamWnd* camwnd = reinterpret_cast( data ); + camwnd->m_window_observer->onMouseMotion( windowvector_for_widget_centre( camwnd->m_gl_widget ), modifiers_for_state( state ) ); +} gboolean wheelmove_scroll( GtkWidget* widget, GdkEventScroll* event, CamWnd* camwnd ){ //gtk_window_set_focus( camwnd->m_parent, camwnd->m_gl_widget ); @@ -1234,7 +1241,8 @@ void CamWnd_Remove_Handlers_Move( CamWnd& camwnd ){ void CamWnd_Add_Handlers_FreeMove( CamWnd& camwnd ){ camwnd.m_selection_button_press_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "button_press_event", G_CALLBACK( selection_button_press_freemove ), camwnd.m_window_observer ); camwnd.m_selection_button_release_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "button_release_event", G_CALLBACK( selection_button_release_freemove ), camwnd.m_window_observer ); - camwnd.m_selection_motion_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "motion_notify_event", G_CALLBACK( selection_motion_freemove ), camwnd.m_window_observer ); + //camwnd.m_selection_motion_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "motion_notify_event", G_CALLBACK( selection_motion_freemove ), camwnd.m_window_observer ); + camwnd.m_selection_motion_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &camwnd.m_deferred_motion_freemove ); camwnd.m_freelook_button_press_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "button_press_event", G_CALLBACK( disable_freelook_button_press ), &camwnd ); @@ -1286,6 +1294,7 @@ CamWnd::CamWnd() : m_XORRectangle( m_gl_widget ), m_deferredDraw( WidgetQueueDrawCaller( *m_gl_widget ) ), m_deferred_motion( selection_motion, m_window_observer ), + m_deferred_motion_freemove( selection_motion_freemove, this ), m_selection_button_press_handler( 0 ), m_selection_button_release_handler( 0 ), m_selection_motion_handler( 0 ), @@ -1989,6 +1998,14 @@ void RenderModeExport( const IntImportCallback& importer ){ } typedef FreeCaller1 RenderModeExportCaller; +void fieldOfViewImport( float value ){ + camera_t::fieldOfView = value; + if( g_camwnd ){ + Camera_updateProjection( g_camwnd->getCamera() ); + } +} +typedef FreeCaller1 fieldOfViewImportCaller; + void Camera_constructPreferences( PreferencesPage& page ){ page.appendSlider( "Movement Speed", g_camwindow_globals_private.m_nMoveSpeed, TRUE, 0, 0, 100, MIN_CAM_SPEED, MAX_CAM_SPEED, 1, 10 ); page.appendCheckBox( "", "Link strafe speed to movement speed", g_camwindow_globals_private.m_bCamLinkSpeed ); @@ -2035,6 +2052,11 @@ void Camera_constructPreferences( PreferencesPage& page ){ g_camwindow_globals_private.m_nStrafeMode, STRING_ARRAY_RANGE( strafe_mode ) ); + + page.appendSpinner( "Field Of View", 110.0, 1.0, 175.0, + FloatImportCallback( fieldOfViewImportCaller() ), + FloatExportCallback( FloatExportCaller( camera_t::fieldOfView ) ) + ); } void Camera_constructPage( PreferenceGroup& group ){ PreferencesPage page( group.createPage( "Camera", "Camera View Preferences" ) ); @@ -2133,6 +2155,7 @@ void CamWnd_Construct(){ GlobalPreferenceSystem().registerPreference( "CameraRenderMode", makeIntStringImportCallback( RenderModeImportCaller() ), makeIntStringExportCallback( RenderModeExportCaller() ) ); GlobalPreferenceSystem().registerPreference( "StrafeMode", IntImportStringCaller( g_camwindow_globals_private.m_nStrafeMode ), IntExportStringCaller( g_camwindow_globals_private.m_nStrafeMode ) ); GlobalPreferenceSystem().registerPreference( "3DZoomInToPointer", BoolImportStringCaller( g_camwindow_globals.m_bZoomInToPointer ), BoolExportStringCaller( g_camwindow_globals.m_bZoomInToPointer ) ); + GlobalPreferenceSystem().registerPreference( "fieldOfView", FloatImportStringCaller( camera_t::fieldOfView ), FloatExportStringCaller( camera_t::fieldOfView ) ); CamWnd_constructStatic(); diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 603f6083..7653e64d 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -59,6 +59,7 @@ void Face_extrude( Face& face, const Brush& brush, brush_vector_t& out, float of */ #include "preferences.h" #include "texwindow.h" +#include "filterbar.h" typedef std::vector doublevector_vector_t; @@ -71,14 +72,6 @@ enum eHollowType room = 4, }; -const char* getCaulkShader(){ - const char* gotShader = g_pGameDescription->getKeyValue( "shader_caulk" ); - if ( gotShader && *gotShader ){ - return gotShader; - } - return "textures/common/caulk"; -} - class CaulkFace { DoubleVector3 ExclusionAxis; @@ -104,7 +97,7 @@ void operator()( Face& face ) const { } } } - face.SetShader( getCaulkShader() ); + face.SetShader( GetCaulkShader() ); } } }; @@ -177,12 +170,12 @@ void operator()( Face& face ) const { face.undoSave(); out.push_back( new Brush( brush ) ); if( !RemoveInner && caulk ) - face.SetShader( getCaulkShader() ); + face.SetShader( GetCaulkShader() ); Face* newFace = out.back()->addFace( face ); face.getPlane().offset( -offset ); face.planeChanged(); if( caulk ) - face.SetShader( getCaulkShader() ); + face.SetShader( GetCaulkShader() ); if ( newFace != 0 ) { newFace->flipWinding(); newFace->getPlane().offset( offset ); @@ -203,7 +196,7 @@ void operator()( Face& face ) const { } if( !RemoveInner && caulk ) - face.SetShader( getCaulkShader() ); + face.SetShader( GetCaulkShader() ); newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->flipWinding(); @@ -233,7 +226,7 @@ void operator()( Face& face ) const { if ( newFace != 0 ) { if( !RemoveInner && caulk ) - newFace->SetShader( getCaulkShader() ); + newFace->SetShader( GetCaulkShader() ); newFace->flipWinding(); newFace->getPlane().offset( offset ); newFace->planeChanged(); @@ -259,7 +252,7 @@ void operator()( Face& face ) const { } } } - out.back()->addPlane( winding[next].vertex, winding[index].vertex, BestPoint, caulk? getCaulkShader() : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), projection ); + out.back()->addPlane( winding[next].vertex, winding[index].vertex, BestPoint, caulk? GetCaulkShader() : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), projection ); } } } diff --git a/radiant/entity.cpp b/radiant/entity.cpp index 5073aac5..52931380 100644 --- a/radiant/entity.cpp +++ b/radiant/entity.cpp @@ -288,6 +288,8 @@ AABB Doom3Light_getBounds( const AABB& workzone ){ return AABB( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); } +#include "filterbar.h" + int g_iLastLightIntensity; void Entity_createFromSelection( const char* name, const Vector3& origin ){ @@ -307,16 +309,10 @@ void Entity_createFromSelection( const char* name, const Vector3& origin ){ bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0; //is important to have retexturing here; if doing in the end, undo doesn't succeed; - if ( string_compare_nocase_n( name, "trigger_", 8 ) == 0 && brushesSelected ){ - const char* shader = g_pGameDescription->getKeyValue( "shader_trigger" ); - if ( shader && *shader ){ - Scene_PatchSetShader_Selected( GlobalSceneGraph(), shader ); - Scene_BrushSetShader_Selected( GlobalSceneGraph(), shader ); - } - else{ - Scene_PatchSetShader_Selected( GlobalSceneGraph(), "textures/common/trigger" ); - Scene_BrushSetShader_Selected( GlobalSceneGraph(), "textures/common/trigger" ); - } + if ( string_compare_nocase_n( name, "trigger_", 8 ) == 0 && brushesSelected && !entityClass->fixedsize ){ + //const char* shader = GetCommonShader( "trigger" ).c_str(); + Scene_PatchSetShader_Selected( GlobalSceneGraph(), GetCommonShader( "trigger" ).c_str() ); + Scene_BrushSetShader_Selected( GlobalSceneGraph(), GetCommonShader( "trigger" ).c_str() ); } if ( !( entityClass->fixedsize || isModel ) && !brushesSelected ) { diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp index 201a4f12..60113063 100644 --- a/radiant/entityinspector.cpp +++ b/radiant/entityinspector.cpp @@ -920,10 +920,17 @@ void SetComment( EntityClass* eclass ){ gtk_text_buffer_apply_tag_by_name( buffer, "bold", &iter_start, &iter_end ); } - if( *c == ' ' ) - ++spaces; - else + if( *c == ' ' ){ + if( offset - pattern_start == 1 ){ + pattern_start = offset; + } + else{ + ++spaces; + } + } + else{ pattern_start = -1; + } } } } @@ -1250,11 +1257,15 @@ void EntityInspector_clearKeyValue(){ } } -static gint EntityInspector_clearKeyValueKB( GtkEntry* widget, GdkEventKey* event, gpointer data ){ +static gint EntityProperties_keypress( GtkEntry* widget, GdkEventKey* event, gpointer data ){ if ( event->keyval == GDK_Delete ) { EntityInspector_clearKeyValue(); return TRUE; } + if ( event->keyval == GDK_Tab ) { + gtk_window_set_focus( GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( widget ) ) ), GTK_WIDGET( g_entityKeyEntry ) ); + return TRUE; + } return FALSE; } @@ -1560,7 +1571,7 @@ GtkWidget* EntityInspector_constructWindow( GtkWindow* toplevel ){ GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) ); gtk_tree_view_set_enable_search( GTK_TREE_VIEW( view ), FALSE ); gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE ); - g_signal_connect( G_OBJECT( view ), "key_press_event", G_CALLBACK( EntityInspector_clearKeyValueKB ), 0 ); + g_signal_connect( G_OBJECT( view ), "key_press_event", G_CALLBACK( EntityProperties_keypress ), 0 ); { GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); diff --git a/radiant/filterbar.cpp b/radiant/filterbar.cpp index 22535702..01460eb6 100644 --- a/radiant/filterbar.cpp +++ b/radiant/filterbar.cpp @@ -23,17 +23,38 @@ gboolean ToggleActions0( GtkWidget *widget, GdkEvent *event, gpointer user_data //globalOutputStream() << "ToggleActions\n"; } -void SetCommonShader( const char* key, const char* shader ){ - const char* gotShader = g_pGameDescription->getKeyValue( key ); - UndoableCommand undo( "textureNameSetSelected" ); - if ( gotShader && *gotShader ){ - Select_SetShader( gotShader ); +CopiedString GetCommonShader( const char* name ){ + StringOutputStream sstream( 128 ); + sstream << "shader_" << name; + const char* gotShader = g_pGameDescription->getKeyValue( sstream.c_str() ); + if( !string_empty( gotShader ) ){ + return gotShader; } else{ - Select_SetShader( shader ); + sstream.clear(); + if( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ){ + sstream << "textures/common/" << name; + } + else{ + sstream << "textures/" << name; + } + return sstream.c_str(); } } +void SetCommonShader( const char* name ){ + UndoableCommand undo( "textureNameSetSelected" ); + Select_SetShader( GetCommonShader( name ).c_str() ); +} + +const char* g_caulk_shader = 0; + +const char* GetCaulkShader(){ + if( !g_caulk_shader ){ + g_caulk_shader = strdup( GetCommonShader( "caulk" ).c_str() ); + } + return g_caulk_shader; +} gboolean Areaportals_button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){ if ( event->button == 3 && event->type == GDK_BUTTON_PRESS ) { @@ -45,13 +66,11 @@ gboolean Areaportals_button_press( GtkWidget *widget, GdkEventButton *event, gpo ButtonNum = 1; } if( ToggleActions == 0 ){ - SetCommonShader( "shader_nodraw", "textures/common/nodraw" ); + SetCommonShader( "nodraw" ); } else if( ToggleActions == 1 ){ - SetCommonShader( "shader_nodrawnonsolid", "textures/common/nodrawnonsolid" ); + SetCommonShader( "nodrawnonsolid" ); } - //SetCommonShader( "shader_caulk", "textures/common/caulk" ); - //globalOutputStream() << "Found '" << "fullname" << "'\n"; ToggleActions++; return TRUE; } @@ -61,7 +80,7 @@ gboolean Areaportals_button_press( GtkWidget *widget, GdkEventButton *event, gpo gboolean Caulk_button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){ if ( event->button == 3 && event->type == GDK_BUTTON_PRESS ) { - SetCommonShader( "shader_caulk", "textures/common/caulk" ); + SetCommonShader( "caulk" ); ToggleActions = 0; return TRUE; } @@ -78,10 +97,10 @@ gboolean Clip_button_press( GtkWidget *widget, GdkEventButton *event, gpointer d ButtonNum = 3; } if( ToggleActions == 0 ){ - SetCommonShader( "shader_clip", "textures/common/clip" ); + SetCommonShader( "clip" ); } else if( ToggleActions == 1 ){ - SetCommonShader( "shader_weapclip", "textures/common/weapclip" ); + SetCommonShader( "weapclip" ); } ToggleActions++; return TRUE; @@ -99,13 +118,13 @@ gboolean Liquids_button_press( GtkWidget *widget, GdkEventButton *event, gpointe ButtonNum = 4; } if( ToggleActions == 0 ){ - SetCommonShader( "shader_watercaulk", "textures/common/watercaulk" ); + SetCommonShader( "watercaulk" ); } else if( ToggleActions == 1 ){ - SetCommonShader( "shader_lavacaulk", "textures/common/lavacaulk" ); + SetCommonShader( "lavacaulk" ); } else if( ToggleActions == 2 ){ - SetCommonShader( "shader_slimecaulk", "textures/common/slimecaulk" ); + SetCommonShader( "slimecaulk" ); } ToggleActions++; return TRUE; @@ -124,13 +143,13 @@ gboolean Hint_button_press( GtkWidget *widget, GdkEventButton *event, gpointer d ButtonNum = 5; } if( ToggleActions == 0 ){ - SetCommonShader( "shader_hint", "textures/common/hint" ); + SetCommonShader( "hint" ); } else if( ToggleActions == 1 ){ - SetCommonShader( "shader_hintlocal", "textures/common/hintlocal" ); + SetCommonShader( "hintlocal" ); } else if( ToggleActions == 2 ){ - SetCommonShader( "shader_hintskip", "textures/common/hintskip" ); + SetCommonShader( "hintskip" ); } ToggleActions++; return TRUE; @@ -140,7 +159,7 @@ gboolean Hint_button_press( GtkWidget *widget, GdkEventButton *event, gpointer d gboolean Trigger_button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){ if ( event->button == 3 && event->type == GDK_BUTTON_PRESS ) { - SetCommonShader( "shader_trigger", "textures/common/trigger" ); + SetCommonShader( "trigger" ); ToggleActions = 0; return TRUE; } diff --git a/radiant/filterbar.h b/radiant/filterbar.h index 7b2888bb..5569ab33 100644 --- a/radiant/filterbar.h +++ b/radiant/filterbar.h @@ -1,16 +1,19 @@ #if !defined( INCLUDED_FILTERBAR_H ) #define INCLUDED_FILTERBAR_H -#include - +//#include "string/string.h" +#include "string/stringfwd.h" +typedef struct _GtkToolbar GtkToolbar; GtkToolbar* create_filter_toolbar(); +CopiedString GetCommonShader( const char* name ); +const char* GetCaulkShader(); #endif diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 9f45a817..9e3d4876 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -1692,6 +1692,10 @@ WaitDialog create_wait_dialog( const char* title, const char* text ){ gtk_container_set_border_width( GTK_CONTAINER( dialog.m_window ), 0 ); gtk_window_set_position( dialog.m_window, GTK_WIN_POS_CENTER_ON_PARENT ); + gtk_window_set_accept_focus( dialog.m_window, FALSE ); + gtk_window_set_focus_on_map( dialog.m_window, FALSE ); + + g_signal_connect( G_OBJECT( dialog.m_window ), "realize", G_CALLBACK( window_realize_remove_decoration ), 0 ); { @@ -1760,7 +1764,10 @@ void ScreenUpdates_Disable( const char* message, const char* title ){ bool isActiveApp = MainFrame_isActiveApp(); g_wait = create_wait_dialog( title, message ); - gtk_grab_add( GTK_WIDGET( g_wait.m_window ) ); + if( !XYWnd::m_mnuDrop || gtk_widget_get_visible( GTK_WIDGET( XYWnd::m_mnuDrop ) ) != TRUE ){ + gtk_grab_add( GTK_WIDGET( g_wait.m_window ) ); + //globalOutputStream() << "grab grab grab\n"; + } if ( isActiveApp ) { gtk_widget_show( GTK_WIDGET( g_wait.m_window ) ); diff --git a/radiant/points.cpp b/radiant/points.cpp index 0a0c3c0f..eb60e6b0 100644 --- a/radiant/points.cpp +++ b/radiant/points.cpp @@ -96,8 +96,10 @@ bool shown() const { void show( bool show ){ if ( show && !shown() ) { Pointfile_Parse( *this ); - GenerateDisplayList(); - SceneChangeNotify(); + if( s_num_points > 0 ){ + GenerateDisplayList(); + SceneChangeNotify(); + } } else if ( !show && shown() ) { glDeleteLists( m_displaylist, 1 ); diff --git a/radiant/selection.cpp b/radiant/selection.cpp index 71c747bf..c10710f7 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -514,6 +514,17 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const start[i] = GetSnapGridSize(); } } + + std::size_t ignore_axis = 0; + if( snap ){ + for ( std::size_t i = 1; i < 3 ; ++i ){ + if( fabs( m_start[i] ) < fabs( m_start[ignore_axis] ) ){ + ignore_axis = i; + } + } + start[ignore_axis] = 0.f; + } + Vector3 scale( start[0] == 0 ? 1 : 1 + delta[0] / start[0], start[1] == 0 ? 1 : 1 + delta[1] / start[1], @@ -522,9 +533,9 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const //globalOutputStream() << "m_start: " << m_start << " start: " << start << " delta: " << delta <<"\n"; for( std::size_t i = 0; i < 3; i++ ){ - if( m_choosen_extent[i] > 0.0625f ){ + if( m_choosen_extent[i] > 0.0625f && start[i] != 0.f ){ scale[i] = ( m_choosen_extent[i] + delta[i] ) / m_choosen_extent[i]; - if( snapbbox && start[i] != 0.f ){ + if( snapbbox ){ float snappdwidth = float_snapped( scale[i] * m_bounds.extents[i] * 2.f, GetSnapGridSize() ); scale[i] = snappdwidth / ( m_bounds.extents[i] * 2.f ); } @@ -532,16 +543,15 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const } //globalOutputStream() << "pre snap scale: " << scale <<"\n"; if( snap ){ - float bestscale = scale[0]; - for( std::size_t i = 1; i < 3; i++ ){ - //if( fabs( 1.0f - fabs( scale[i] ) ) > fabs( 1.0f - fabs( bestscale ) ) ){ - if( fabs( scale[i] ) > fabs( bestscale ) && scale[i] != 1.0f ){ //harder to scale down with this, but glitchier with upper one + float bestscale = ignore_axis != 0 ? scale[0] : scale[1]; + for( std::size_t i = ignore_axis != 0 ? 1 : 2; i < 3; i++ ){ + if( ignore_axis != i && fabs( scale[i] ) < fabs( bestscale ) ){ bestscale = scale[i]; } //globalOutputStream() << "bestscale: " << bestscale <<"\n"; } for( std::size_t i = 0; i < 3; i++ ){ - if( start[i] != 0.0f ){ // !!!!check grid == 0 case + if( ignore_axis != i ){ scale[i] = ( scale[i] < 0.0f ) ? -fabs( bestscale ) : fabs( bestscale ); } } @@ -2638,7 +2648,7 @@ std::list& best(){ } }; -bool g_bAltDragManipulatorResize = false; //+select primitives in component modes +bool g_bAltResize_AltSelect = false; //AltDragManipulatorResize + select primitives in component modes bool g_bTmpComponentMode = false; class DragManipulator : public Manipulator @@ -2670,7 +2680,7 @@ void testSelect( const View& view, const Matrix4& pivot2world ){ Scene_TestSelect_Primitive( booleanSelector, test, view ); if ( booleanSelector.isSelected() ) { - if( g_bAltDragManipulatorResize ){ + if( g_bAltResize_AltSelect ){ DeepBestSelector deepSelector; Scene_TestSelect_Component_Selected( deepSelector, test, view, SelectionSystem::eVertex ); for ( std::list::iterator i = deepSelector.best().begin(); i != deepSelector.best().end(); ++i ) @@ -2695,7 +2705,7 @@ void testSelect( const View& view, const Matrix4& pivot2world ){ } else { - if( g_bAltDragManipulatorResize ){ + if( g_bAltResize_AltSelect ){ Scene_forEachBrushPlane_selectVertices( GlobalSceneGraph(), test ); m_selected = true; } @@ -3157,7 +3167,7 @@ void SelectPoint( const View& view, const float device_point[2], const float dev Scene_TestSelect_Component( selector, volume, scissored, eFace ); } else{ - Scene_TestSelect( selector, volume, scissored, g_bAltDragManipulatorResize ? ePrimitive : Mode(), ComponentMode() ); + Scene_TestSelect( selector, volume, scissored, g_bAltResize_AltSelect ? ePrimitive : Mode(), ComponentMode() ); } if ( !selector.failed() ) { @@ -3220,7 +3230,7 @@ void SelectPoint( const View& view, const float device_point[2], const float dev ++i; while ( i != selector.end() ) { - if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){ + if( ( *i ).first.equalEpsilon( ( *best ).first, Mode() == eComponent ? 0.25f : 0.000001f, 0.000001f ) ){ if( !( *i ).second->isSelected() ){ ( *i ).second->setSelected( true ); } @@ -3242,7 +3252,7 @@ void SelectPoint( const View& view, const float device_point[2], const float dev ++i; while ( i != selector.end() ) { - if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){ + if( ( *i ).first.equalEpsilon( ( *best ).first, Mode() == eComponent ? 0.25f : 0.000001f, 0.000001f ) ){ if( ( *i ).second->isSelected() ){ ( *i ).second->setSelected( false ); } @@ -3306,7 +3316,7 @@ bool SelectPoint_InitPaint( const View& view, const float device_point[2], const Scene_TestSelect_Component( selector, volume, scissored, eFace ); } else{ - Scene_TestSelect( selector, volume, scissored, g_bAltDragManipulatorResize ? ePrimitive : Mode(), ComponentMode() ); + Scene_TestSelect( selector, volume, scissored, g_bAltResize_AltSelect ? ePrimitive : Mode(), ComponentMode() ); } if ( !selector.failed() ){ SelectableSortedSet::iterator best = selector.begin(); @@ -3316,7 +3326,7 @@ bool SelectPoint_InitPaint( const View& view, const float device_point[2], const ++i; while ( i != selector.end() ) { - if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){ + if( ( *i ).first.equalEpsilon( ( *best ).first, Mode() == eComponent ? 0.25f : 0.000001f, 0.000001f ) ){ ( *i ).second->setSelected( !wasSelected ); } else{ @@ -3680,7 +3690,7 @@ void RadiantSelectionSystem::endMove(){ if ( Mode() == ePrimitive ) { if ( ManipulatorMode() == eDrag ) { g_bTmpComponentMode = false; - if( g_bAltDragManipulatorResize ){ + if( g_bAltResize_AltSelect ){ Scene_SelectAll_Component( false, SelectionSystem::eVertex ); } else{ @@ -4286,7 +4296,7 @@ void onMouseDown( const WindowVector& position, ButtonIdentifier button, Modifie //m_selector.m_mouseMoved = false; DeviceVector devicePosition( window_to_normalised_device( position, m_width, m_height ) ); - g_bAltDragManipulatorResize = ( modifiers == c_modifierAlt ) ? true : false; + g_bAltResize_AltSelect = ( modifiers == c_modifierAlt ) ? true : false; if ( ( modifiers == c_modifier_manipulator || ( modifiers == c_modifierAlt && getSelectionSystem().Mode() != SelectionSystem::eComponent ) ) && m_manipulator.mouseDown( devicePosition ) ) { g_mouseMovedCallback.insert( MouseEventCallback( Manipulator_::MouseMovedCaller( m_manipulator ) ) ); g_mouseUpCallback.insert( MouseEventCallback( Manipulator_::MouseUpCaller( m_manipulator ) ) ); diff --git a/radiant/textures.cpp b/radiant/textures.cpp index b223e2ee..c0477d92 100644 --- a/radiant/textures.cpp +++ b/radiant/textures.cpp @@ -728,7 +728,7 @@ void Textures_constructPreferences( PreferencesPage& page ){ "Texture Gamma", 1.0, 0.0, - 1.0, + 5.0, FloatImportCallback( TextureGammaImportCaller( g_texture_globals.fGamma ) ), FloatExportCallback( FloatExportCaller( g_texture_globals.fGamma ) ) ); diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 5d58f3d7..650436b7 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -393,13 +393,14 @@ void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const cha } // disable the menu item "shader info" if no shader was selected + if ( textureBrowser.m_shader_info_item == NULL ){ + return; + } IShader* ishader = QERApp_Shader_ForName( shader ); CopiedString filename = ishader->getShaderFileName(); if ( filename.empty() ) { - if ( textureBrowser.m_shader_info_item != NULL ) { - gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, FALSE ); - } + gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, FALSE ); } else { gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, TRUE ); @@ -782,9 +783,15 @@ void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* d textureBrowser.m_searchedTags = false; if ( TextureBrowser_showWads() ) { Archive* archive = GlobalFileSystem().getArchive( directory ); - ASSERT_NOTNULL( archive ); - LoadShaderVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, 0 ), "textures/" ); + //ASSERT_NOTNULL( archive ); + if( archive ){ + globalOutputStream() << "Loading " << makeQuoted( directory ) << " wad file.\n"; + LoadShaderVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, 0 ), "textures/" ); + } + else{ + globalErrorStream() << "Attempted to load " << makeQuoted( directory ) << " wad file.\n"; + } } else { @@ -1406,7 +1413,8 @@ gboolean TextureBrowser_button_press( GtkWidget* widget, GdkEventButton* event, } } } - else if ( event->type == GDK_2BUTTON_PRESS && event->button == 1 ) { + /* loads directory, containing active shader + focuses on it */ + else if ( event->type == GDK_2BUTTON_PRESS && event->button == 1 && !TextureBrowser_showWads() ) { CopiedString texName = textureBrowser->shader; char* sh = const_cast( texName.c_str() ); char* dir = strrchr( sh, '/' ); @@ -1569,6 +1577,22 @@ void TextureGroups_constructTreeModel( TextureGroups groups, GtkTreeStore* store } } +void TextureGroups_constructTreeModel_childless( TextureGroups groups, GtkTreeStore* store ){ + // put the information from the old textures menu into a treeview + GtkTreeIter iter; + + TextureGroups::const_iterator i = groups.begin(); + while ( i != groups.end() ) + { + const char* dirName = ( *i ).c_str(); + { + gtk_tree_store_append( store, &iter, NULL ); + gtk_tree_store_set( store, &iter, 0, dirName, -1 ); + ++i; + } + } +} + TextureGroups TextureGroups_constructTreeView(){ TextureGroups groups; @@ -1591,7 +1615,12 @@ TextureGroups TextureGroups_constructTreeView(){ void TextureBrowser_constructTreeStore(){ TextureGroups groups = TextureGroups_constructTreeView(); GtkTreeStore* store = gtk_tree_store_new( 1, G_TYPE_STRING ); - TextureGroups_constructTreeModel( groups, store ); + if( !TextureBrowser_showWads() ){ + TextureGroups_constructTreeModel( groups, store ); + } + else{ + TextureGroups_constructTreeModel_childless( groups, store ); + } //std::set::iterator iter; GtkTreeModel* model = GTK_TREE_MODEL( store ); @@ -1729,7 +1758,7 @@ GtkMenuItem* TextureBrowser_constructViewMenu( GtkMenu* menu ){ // we always want to show shaders but don't want a "Show Shaders" menu for doom3 and .wad file games - if ( g_pGameDescription->mGameType == "doom3" || !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + if ( g_pGameDescription->mGameType == "doom3" || TextureBrowser_showWads() ) { g_TextureBrowser.m_showShaders = true; } else @@ -1742,10 +1771,10 @@ GtkMenuItem* TextureBrowser_constructViewMenu( GtkMenu* menu ){ if ( g_TextureBrowser.m_tags ) { create_menu_item_with_mnemonic( menu, "Show Untagged", "ShowUntagged" ); } - if ( g_pGameDescription->mGameType != "doom3" && string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + if ( g_pGameDescription->mGameType != "doom3" && !TextureBrowser_showWads() ) { create_check_menu_item_with_mnemonic( menu, "ShaderList Only", "ToggleShowShaderlistOnly" ); } - if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + if ( !TextureBrowser_showWads() ) { create_check_menu_item_with_mnemonic( menu, "Hide Image Missing", "FilterNotex" ); menu_separator( menu ); } @@ -1753,7 +1782,7 @@ GtkMenuItem* TextureBrowser_constructViewMenu( GtkMenu* menu ){ create_check_menu_item_with_mnemonic( menu, "Fixed Size", "FixedSize" ); create_check_menu_item_with_mnemonic( menu, "Transparency", "EnableAlpha" ); - if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + if ( !TextureBrowser_showWads() ) { menu_separator( menu ); g_TextureBrowser.m_shader_info_item = GTK_WIDGET( create_menu_item_with_mnemonic( menu, "Shader Info", "ShaderInfo" ) ); gtk_widget_set_sensitive( g_TextureBrowser.m_shader_info_item, FALSE ); @@ -2739,8 +2768,8 @@ void TextureBrowser_constructPreferences( PreferencesPage& page ){ IntExportCallback( TextureScaleExportCaller( GlobalTextureBrowser() ) ) ); } - page.appendSpinner( "Thumbnails Max Size", GlobalTextureBrowser().m_uniformTextureSize, GlobalTextureBrowser().m_uniformTextureSize, 16, 8192 ); - page.appendSpinner( "Thumbnails Min Size", GlobalTextureBrowser().m_uniformTextureMinSize, GlobalTextureBrowser().m_uniformTextureMinSize, 16, 8192 ); + page.appendSpinner( "Thumbnails Max Size", GlobalTextureBrowser().m_uniformTextureSize, 160.0, 16, 8192 ); + page.appendSpinner( "Thumbnails Min Size", GlobalTextureBrowser().m_uniformTextureMinSize, 48.0, 16, 8192 ); page.appendEntry( "Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement ); { const char* startup_shaders[] = { "None", TextureBrowser_getComonShadersName() }; diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 623f74a2..341eeb30 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -248,8 +248,10 @@ void Clip_Update(){ ClipperChangeNotify(); } +#include "filterbar.h" + const char* Clip_getShader(){ - return g_clip_useCaulk ? "textures/common/caulk" : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ); + return g_clip_useCaulk ? GetCaulkShader() : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ); } void Clip(){ @@ -1184,35 +1186,12 @@ void XYWnd::NewBrushDrag( int x, int y ){ //Scene_BrushResize_Selected(GlobalSceneGraph(), aabb_for_minmax(mins, maxs), TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); Scene_BrushResize_Selected( GlobalSceneGraph(), aabb_for_minmax( mins, maxs ), g_brush_always_caulk ? - "textures/common/caulk" : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); + GetCaulkShader() : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); } -gboolean entitycreate_rightClicked( GtkWidget* widget, GdkEvent* event, gpointer user_data ) { - if ( event->button.button == 3 ) { -// globalOutputStream() << "yo+\n"; +int g_entityCreationOffset = 0; - const char* entity_name = gtk_label_get_text( GTK_LABEL( GTK_BIN( widget )->child ) ); - StringOutputStream command; - command << "entitySetClass -class " << entity_name; - UndoableCommand undo( command.c_str() ); - - Scene_EntitySetClassname_Selected( entity_name ); - - gtk_menu_popdown( XYWnd::m_mnuDrop ); - return TRUE; - } - return FALSE; -} - -gboolean entitycreate_rightUnClicked( GtkWidget* widget, GdkEvent* event, gpointer user_data ) { - if ( event->button.button == 3 ) { -// globalOutputStream() << "yo-\n"; - return TRUE; - } - return FALSE; -} - -void entitycreate_activated( GtkWidget* item ){ +void entitycreate_activated( GtkMenuItem* item, gpointer user_data ){ scene::Node* world_node = Map_FindWorldspawn( g_map ); const char* entity_name = gtk_label_get_text( GTK_LABEL( GTK_BIN( item )->child ) ); @@ -1229,13 +1208,15 @@ void entitycreate_activated( GtkWidget* item ){ viewvector[1] = sin( radangles[1] ) * cos( radangles[0] ); viewvector[2] = sin( radangles[0] ); - Vector3 point = viewvector * 64.f + Camera_getOrigin( *g_pParentWnd->GetCamWnd() ); + float offset_for_multiple = ( GetSnapGridSize() < 8.f ? 8.f : GetSnapGridSize() ) * g_entityCreationOffset; + Vector3 point = viewvector * ( 64.f + offset_for_multiple ) + Camera_getOrigin( *g_pParentWnd->GetCamWnd() ); vector3_snap( point, GetSnapGridSize() ); Entity_createFromSelection( entity_name, point ); } else{ g_pParentWnd->ActiveXY()->OnEntityCreate( entity_name ); } + ++g_entityCreationOffset; } else { GlobalRadiant().m_pfnMessageBox( GTK_WIDGET( MainFrame_getWindow() ), "There's already a worldspawn in your map!" @@ -1246,11 +1227,48 @@ void entitycreate_activated( GtkWidget* item ){ } } +gboolean entitycreate_rightClicked( GtkWidget* widget, GdkEvent* event, gpointer user_data ) { + /* convert entities */ + if ( event->button.button == 3 ) { +// globalOutputStream() << "yo+\n"; + + const char* entity_name = gtk_label_get_text( GTK_LABEL( GTK_BIN( widget )->child ) ); + StringOutputStream command; + command << "entitySetClass -class " << entity_name; + UndoableCommand undo( command.c_str() ); + + Scene_EntitySetClassname_Selected( entity_name ); + + if( ( event->button.state & GDK_CONTROL_MASK ) == 0 ){ + gtk_menu_popdown( XYWnd::m_mnuDrop ); + } + return TRUE; + } + /* create entities, don't close menu */ + else if ( event->button.button == 1 && ( ( event->button.state & GDK_CONTROL_MASK ) != 0 || gtk_menu_get_tearoff_state( XYWnd::m_mnuDrop ) == TRUE ) ) { + entitycreate_activated( GTK_MENU_ITEM( widget ), 0 ); + return TRUE; + } + return FALSE; +} + +/* This handles unwanted rightclick release, that can occur with low res display, while activating menu from camera (=activate top menu entry) */ +gboolean entitycreate_rightUnClicked( GtkWidget* widget, GdkEvent* event, gpointer user_data ) { + if ( event->button.button == 3 ) { +// globalOutputStream() << "yo-\n"; + return TRUE; + } + else if ( event->button.button == 1 && ( ( event->button.state & GDK_CONTROL_MASK ) != 0 || gtk_menu_get_tearoff_state( XYWnd::m_mnuDrop ) == TRUE ) ) { + return TRUE; + } + return FALSE; +} + void EntityClassMenu_addItem( GtkMenu* menu, const char* name ){ GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_label( name ) ); - g_signal_connect( G_OBJECT( item ), "button-press-event", G_CALLBACK( entitycreate_rightClicked ), item ); - g_signal_connect( G_OBJECT( item ), "button-release-event", G_CALLBACK( entitycreate_rightUnClicked ), item ); - g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( entitycreate_activated ), item ); + g_signal_connect( G_OBJECT( item ), "button-press-event", G_CALLBACK( entitycreate_rightClicked ), 0 ); + g_signal_connect( G_OBJECT( item ), "button-release-event", G_CALLBACK( entitycreate_rightUnClicked ), 0 ); + g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( entitycreate_activated ), 0 ); gtk_widget_show( GTK_WIDGET( item ) ); menu_add_item( menu, item ); } @@ -1327,11 +1345,16 @@ void XYWnd::OnContextMenu(){ if ( m_mnuDrop == 0 ) { // first time, load it up GtkMenu* menu = m_mnuDrop = GTK_MENU( gtk_menu_new() ); +// menu_tearoff( menu ); + g_signal_connect( G_OBJECT( menu_tearoff( menu ) ), "button-release-event", G_CALLBACK( entitycreate_rightUnClicked ), 0 ); + gtk_menu_attach_to_widget( m_mnuDrop, GTK_WIDGET( m_parent != 0 ? m_parent : MainFrame_getWindow() ), NULL ); + gtk_menu_set_title( m_mnuDrop, "" ); EntityClassMenuInserter inserter( menu ); GlobalEntityClassManager().forEach( inserter ); } + g_entityCreationOffset = 0; g_bCamEntityMenu = false; gtk_menu_popup( m_mnuDrop, 0, 0, 0, 0, 1, GDK_CURRENT_TIME ); } @@ -1659,7 +1682,7 @@ void XYWnd::XY_LoadBackgroundImage( const char *name ){ m_ix = 0; m_iy = 2; break; - case YZ: + default: //case YZ: m_ix = 1; m_iy = 2; break; @@ -2760,6 +2783,21 @@ void XYWnd::OnEntityCreate( const char* item ){ UndoableCommand undo( command.c_str() ); Vector3 point; XYWnd_MouseToPoint( this, m_entityCreate_x, m_entityCreate_y, point ); + + Vector3 offset( 0, 0, 0 ); + float offset_for_multiple = ( GetSnapGridSize() < 8.f ? 8.f : GetSnapGridSize() ) * g_entityCreationOffset; + switch ( m_viewType ) + { + case XY: + case XZ: + offset[0] = 1.f; + break; + default: //case YZ: + offset[1] = 1.f; + break; + } + point += offset * offset_for_multiple; + Entity_createFromSelection( item, point ); }