diff --git a/radiant/brush_primit.cpp b/radiant/brush_primit.cpp index e99b0972..a002358d 100644 --- a/radiant/brush_primit.cpp +++ b/radiant/brush_primit.cpp @@ -663,6 +663,7 @@ void TexMatToFakeTexCoords( const brushprimit_texdef_t& bp_texdef, texdef_t& tex // compute back the texture matrix from fake shift scale rot void FakeTexCoordsToTexMat( const texdef_t& texdef, brushprimit_texdef_t& bp_texdef ){ +#if 1 double r = degrees_to_radians( -texdef.rotate ); double c = cos( r ); double s = sin( r ); @@ -674,6 +675,20 @@ void FakeTexCoordsToTexMat( const texdef_t& texdef, brushprimit_texdef_t& bp_tex bp_texdef.coords[1][1] = static_cast( y * c ); bp_texdef.coords[0][2] = -texdef.shift[0]; bp_texdef.coords[1][2] = texdef.shift[1]; +#else + double r = degrees_to_radians( texdef.rotate ); + double c = cos( r ); + double s = sin( r ); + double x = 1.0f / texdef.scale[0]; + double y = 1.0f / texdef.scale[1]; + bp_texdef.coords[0][0] = static_cast( x * c ); + bp_texdef.coords[1][0] = static_cast( -y * s ); + bp_texdef.coords[0][1] = static_cast( x * s ); + bp_texdef.coords[1][1] = static_cast( y * c ); + bp_texdef.coords[0][2] = -texdef.shift[0]; + bp_texdef.coords[1][2] = texdef.shift[1]; +#endif +// globalOutputStream() << "[ " << bp_texdef.coords[0][0] << " " << bp_texdef.coords[0][1] << " ][ " << bp_texdef.coords[1][0] << " " << bp_texdef.coords[1][1] << " ]\n"; } #if 0 // texture locking (brush primit) @@ -1349,7 +1364,7 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s identity2stOriginal = matrix4_multiplied_by_matrix4( identity2stOriginal, identityCorrected ); } - else if( dot != dot ){ //catch QNAN: happens on scaling cuboid on Z and sometimes on rotating + else if( dot != dot ){ //catch QNAN: happens on scaling cuboid on Z and sometimes on rotating (in bp mode) return; } diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index 754ed97b..3a02277c 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -579,7 +579,6 @@ void operator()( Face& face ) const { class FaceFindShader { const char* m_find; -const char* m_replace; public: FaceFindShader( const char* find ) : m_find( find ){ } @@ -590,6 +589,10 @@ void operator()( FaceInstance& faceinst ) const { } }; +void Scene_BrushFacesSelectByShader( scene::Graph& graph, const char* name ){ + Scene_ForEachBrush_ForEachFaceInstance( graph, FaceFindShader( name ) ); +} + bool DoingSearch( const char *repl ){ return ( repl == NULL || ( strcmp( "textures/", repl ) == 0 ) ); } diff --git a/radiant/brushmanip.h b/radiant/brushmanip.h index 411cf332..7302460d 100644 --- a/radiant/brushmanip.h +++ b/radiant/brushmanip.h @@ -68,6 +68,7 @@ void Scene_BrushFindReplaceShader_Selected( scene::Graph& graph, const char* fin void Scene_BrushFindReplaceShader_Component_Selected( scene::Graph& graph, const char* find, const char* replace ); void Scene_BrushSelectByShader( scene::Graph& graph, const char* name ); void Scene_BrushSelectByShader_Component( scene::Graph& graph, const char* name ); +void Scene_BrushFacesSelectByShader( scene::Graph& graph, const char* name ); #include "itexdef.h" template class BasicVector3; diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index 17ea0e90..a60f390c 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -320,6 +320,7 @@ void Camera_FreeMove( camera_t& camera, int dx, int dy ){ Camera_Freemove_updateAxes( camera ); } +#if 0 void Cam_MouseControl( camera_t& camera, int x, int y ){ // int xl, xh; // int yl, yh; @@ -353,6 +354,7 @@ void Cam_MouseControl( camera_t& camera, int x, int y ){ Camera_updateModelview( camera ); } +#endif // 0 void Camera_mouseMove( camera_t& camera, int x, int y ){ //globalOutputStream() << "mousemove... "; @@ -655,17 +657,17 @@ void Camera_motionDelta( int x, int y, unsigned int state, void* data ){ cam->m_strafe = false; break; case 1: - cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 && ( state & GDK_SHIFT_MASK ) == 0; + cam->m_strafe = ( ( state & GDK_CONTROL_MASK ) != 0 || ( state & GDK_BUTTON3_MASK ) != 0 ) && ( state & GDK_SHIFT_MASK ) == 0; cam->m_strafe_forward = false; break; case 2: - cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 && ( state & GDK_SHIFT_MASK ) == 0; + cam->m_strafe = ( ( state & GDK_CONTROL_MASK ) != 0 || ( state & GDK_BUTTON3_MASK ) != 0 ) && ( state & GDK_SHIFT_MASK ) == 0; cam->m_strafe_forward = cam->m_strafe; break; case 4: cam->m_strafe_forward_invert = true; default: - cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0; + cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 || ( state & GDK_BUTTON3_MASK ) != 0; if ( cam->m_strafe ) { cam->m_strafe_forward = ( state & GDK_SHIFT_MASK ) != 0; } @@ -674,6 +676,11 @@ void Camera_motionDelta( int x, int y, unsigned int state, void* data ){ } break; } + + if( ( state & GDK_BUTTON1_MASK ) != 0 ){ + cam->m_strafe = true; + cam->m_strafe_forward = false; + } } @@ -713,6 +720,7 @@ guint m_selection_button_release_handler; guint m_selection_motion_handler; guint m_freelook_button_press_handler; +guint m_freelook_button_release_handler; guint m_sizeHandler; guint m_exposeHandler; @@ -752,6 +760,7 @@ void Cam_ChangeFloor( bool up ); void DisableFreeMove(); void EnableFreeMove(); bool m_bFreeMove; +bool m_bFreeMove_entering; CameraView& getCameraView(){ return m_cameraview; @@ -863,12 +872,13 @@ void context_menu(){ /* GDK_2BUTTON_PRESS doesn't always work in this case, so... */ bool context_menu_try( CamWnd* camwnd ){ //globalOutputStream() << camwnd->m_rightClickTimer.elapsed_msec() << "\n"; - return camwnd->m_rightClickTimer.elapsed_msec() < 200; + return camwnd->m_rightClickTimer.elapsed_msec() < 250; //doesn't work if cam redraw > 200msec (3x click works): gtk_widget_queue_draw proceeds after timer.start() } gboolean enable_freelook_button_press( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){ if ( event->type == GDK_BUTTON_PRESS && event->button == 3 && modifiers_for_state( event->state ) == c_modifierNone ) { + camwnd->m_bFreeMove_entering = true; if( context_menu_try( camwnd ) ){ context_menu(); } @@ -883,9 +893,10 @@ gboolean enable_freelook_button_press( GtkWidget* widget, GdkEventButton* event, gboolean disable_freelook_button_press( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){ if ( event->type == GDK_BUTTON_PRESS && event->button == 3 && modifiers_for_state( event->state ) == c_modifierNone ) { + camwnd->m_bFreeMove_entering = false; bool doubleclicked = context_menu_try( camwnd ); - camwnd->DisableFreeMove(); if( doubleclicked ){ + camwnd->DisableFreeMove(); context_menu(); } else{ @@ -896,6 +907,17 @@ gboolean disable_freelook_button_press( GtkWidget* widget, GdkEventButton* event return FALSE; } +gboolean disable_freelook_button_release( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){ + if ( event->type == GDK_BUTTON_RELEASE && event->button == 3 && modifiers_for_state( event->state ) == c_modifierNone ) { + if( ( camwnd->m_rightClickTimer.elapsed_msec() > 300 && camwnd->m_bFreeMove_entering ) || + ( camwnd->m_rightClickTimer.elapsed_msec() < 300 && !camwnd->m_bFreeMove_entering ) ){ + camwnd->DisableFreeMove(); + return TRUE; + } + } + return FALSE; +} + #if 0 gboolean mousecontrol_button_press( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){ if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) { @@ -1266,6 +1288,7 @@ void CamWnd_Add_Handlers_FreeMove( CamWnd& camwnd ){ 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 ); + camwnd.m_freelook_button_release_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "button_release_event", G_CALLBACK( disable_freelook_button_release ), &camwnd ); KeyEvent_connect( "CameraFreeMoveForward" ); KeyEvent_connect( "CameraFreeMoveBack" ); @@ -1304,6 +1327,7 @@ void CamWnd_Remove_Handlers_FreeMove( CamWnd& camwnd ){ g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_motion_handler ); g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_freelook_button_press_handler ); + g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_freelook_button_release_handler ); } CamWnd::CamWnd() : @@ -1320,6 +1344,7 @@ CamWnd::CamWnd() : m_selection_button_release_handler( 0 ), m_selection_motion_handler( 0 ), m_freelook_button_press_handler( 0 ), + m_freelook_button_release_handler( 0 ), m_drawing( false ){ m_bFreeMove = false; diff --git a/radiant/environment.cpp b/radiant/environment.cpp index a5f5e2dc..ee6bceee 100644 --- a/radiant/environment.cpp +++ b/radiant/environment.cpp @@ -104,17 +104,16 @@ bool gamedetect_check_game( const char *gamefile, const char *checkfile1, const void gamedetect(){ // if we're inside a Nexuiz install // default to nexuiz.game (unless the user used an option to inhibit this) - //bool nogamedetect = false; - bool nogamedetect = true; + bool gamedetect = false; int i; - for ( i = 1; i < g_argc - 1; ++i ) - if ( g_argv[i][0] == '-' ) { - if ( !strcmp( g_argv[i], "-gamedetect" ) ) { - nogamedetect = !strcmp( g_argv[i + 1], "false" ); - } - ++i; + for ( i = 1; i < g_argc; ++i ){ + if ( !strcmp( g_argv[i], "-gamedetect" ) ) { + gamedetect = true; + //nogamedetect = !strcmp( g_argv[i + 1], "false" ); + break; } - if ( !nogamedetect ) { + } + if ( gamedetect ) { static char buf[1024 + 64]; strncpy( buf, environment_get_app_path(), sizeof( buf ) ); buf[sizeof( buf ) - 1 - 64] = 0; diff --git a/radiant/gtkdlgs.cpp b/radiant/gtkdlgs.cpp index e1d986df..fe5135a0 100644 --- a/radiant/gtkdlgs.cpp +++ b/radiant/gtkdlgs.cpp @@ -904,8 +904,18 @@ static void DoGtkTextEditor( const char* filename, guint cursorpos, int length ) // ============================================================================= // Light Intensity dialog +#include + +bool g_dontDoLightIntensityDlg = false; + +void dontDoLightIntensityDlg_toggled( GtkToggleButton* togglebutton, gpointer user_data ){ + g_dontDoLightIntensityDlg = gtk_toggle_button_get_active( togglebutton ); +} EMessageBoxReturn DoLightIntensityDlg( int *intensity ){ + if( g_dontDoLightIntensityDlg ){ + return eIDOK; + } ModalDialog dialog; GtkEntry* intensity_entry; ModalDialogButton ok_button( dialog, eIDOK ); @@ -936,6 +946,13 @@ EMessageBoxReturn DoLightIntensityDlg( int *intensity ){ intensity_entry = entry; } + { + GtkWidget* check = gtk_check_button_new_with_label( "Don't Show" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check ), FALSE ); + gtk_widget_show( check ); + gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); + g_signal_connect( G_OBJECT( check ), "toggled", G_CALLBACK( dontDoLightIntensityDlg_toggled ), 0 ); + } } { GtkVBox* vbox = create_dialog_vbox( 4 ); diff --git a/radiant/main.cpp b/radiant/main.cpp index 7d3a5a79..b69ec2b9 100644 --- a/radiant/main.cpp +++ b/radiant/main.cpp @@ -564,25 +564,26 @@ int main( int argc, char* argv[] ){ streams_init(); #ifdef WIN32 - HMODULE lib; - lib = LoadLibrary( "dwmapi.dll" ); - if ( lib != 0 ) { - void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" ); - if ( qDwmEnableComposition ) { - bool Aero = false; - for ( int i = 1; i < argc; ++i ){ - if ( !stricmp( argv[i], "-aero" ) ){ - Aero = true; - qDwmEnableComposition( TRUE ); - break; - } - } - // disable Aero - if ( !Aero ){ - qDwmEnableComposition( FALSE ); + { + bool aero = true; + for ( int i = 1; i < argc; ++i ){ + if ( !stricmp( argv[i], "-aero" ) ){ + aero = false; + break; + } + } + if( !aero ){ + HMODULE lib; + lib = LoadLibrary( "dwmapi.dll" ); + if ( lib != 0 ) { + void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" ); + if ( qDwmEnableComposition ) { + // disable Aero + qDwmEnableComposition( FALSE ); + } + FreeLibrary( lib ); } } - FreeLibrary( lib ); } _setmaxstdio(2048); #endif diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 868d9605..72c43c45 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -1987,6 +1987,7 @@ GtkMenuItem* create_edit_menu(){ // menu_tearoff( convert_menu ); // } create_menu_item_with_mnemonic( menu, "Select All Of Type", "SelectAllOfType" ); + create_menu_item_with_mnemonic( menu, "Select Textured", "SelectTextured" ); create_menu_item_with_mnemonic( menu, "_Expand Selection To Primitives", "ExpandSelectionToPrimitives" ); create_menu_item_with_mnemonic( menu, "_Expand Selection To Entities", "ExpandSelectionToEntities" ); create_menu_item_with_mnemonic( menu, "Select Connected Entities", "SelectConnectedEntities" ); diff --git a/radiant/map.cpp b/radiant/map.cpp index cba9fad9..c3141c1c 100644 --- a/radiant/map.cpp +++ b/radiant/map.cpp @@ -1448,13 +1448,13 @@ void ConstructRegionStartpoint( scene::Node* startpoint, const Vector3& region_m =========================================================== */ -bool region_active = false; +bool g_region_active = false; -BoolExportCaller g_region_caller( region_active ); +BoolExportCaller g_region_caller( g_region_active ); ToggleItem g_region_item( g_region_caller ); -Vector3 region_mins( g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord ); -Vector3 region_maxs( g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord ); +Vector3 g_region_mins( g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord ); +Vector3 g_region_maxs( g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord ); scene::Node* region_sides[6]; scene::Node* region_startpoint = 0; @@ -1479,8 +1479,8 @@ void AddRegionBrushes( void ){ region_startpoint = &GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "info_player_start", false ) ); - ConstructRegionBrushes( region_sides, region_mins, region_maxs ); - ConstructRegionStartpoint( region_startpoint, region_mins, region_maxs ); + ConstructRegionBrushes( region_sides, g_region_mins, g_region_maxs ); + ConstructRegionStartpoint( region_startpoint, g_region_mins, g_region_maxs ); Node_getTraversable( GlobalSceneGraph().root() )->insert( NodeSmartReference( *region_startpoint ) ); } @@ -1553,7 +1553,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { ( aabb_intersects_aabb( instance.worldAABB(), - aabb_for_minmax( region_mins, region_maxs ) + aabb_for_minmax( g_region_mins, g_region_maxs ) ) != 0 ) ^ m_exclude ) @@ -1575,21 +1575,21 @@ void Scene_Exclude_Region( bool exclude ){ =========== */ void Map_RegionOff(){ - region_active = false; + g_region_active = false; g_region_item.update(); - region_maxs[0] = g_MaxWorldCoord - 64; - region_mins[0] = g_MinWorldCoord + 64; - region_maxs[1] = g_MaxWorldCoord - 64; - region_mins[1] = g_MinWorldCoord + 64; - region_maxs[2] = g_MaxWorldCoord - 64; - region_mins[2] = g_MinWorldCoord + 64; + g_region_maxs[0] = g_MaxWorldCoord - 64; + g_region_mins[0] = g_MinWorldCoord + 64; + g_region_maxs[1] = g_MaxWorldCoord - 64; + g_region_mins[1] = g_MinWorldCoord + 64; + g_region_maxs[2] = g_MaxWorldCoord - 64; + g_region_mins[2] = g_MinWorldCoord + 64; Scene_Exclude_All( false ); } void Map_ApplyRegion( void ){ - region_active = true; + g_region_active = true; g_region_item.update(); Scene_Exclude_Region( false ); @@ -1606,9 +1606,9 @@ void Map_RegionSelectedBrushes( void ){ if ( GlobalSelectionSystem().countSelected() != 0 && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { - region_active = true; + g_region_active = true; g_region_item.update(); - Select_GetBounds( region_mins, region_maxs ); + Select_GetBounds( g_region_mins, g_region_maxs ); Scene_Exclude_Selected( false ); @@ -1625,12 +1625,12 @@ void Map_RegionSelectedBrushes( void ){ void Map_RegionXY( float x_min, float y_min, float x_max, float y_max ){ Map_RegionOff(); - region_mins[0] = x_min; - region_maxs[0] = x_max; - region_mins[1] = y_min; - region_maxs[1] = y_max; - region_mins[2] = g_MinWorldCoord + 64; - region_maxs[2] = g_MaxWorldCoord - 64; + g_region_mins[0] = x_min; + g_region_maxs[0] = x_max; + g_region_mins[1] = y_min; + g_region_maxs[1] = y_max; + g_region_mins[2] = g_MinWorldCoord + 64; + g_region_maxs[2] = g_MaxWorldCoord - 64; Map_ApplyRegion(); } @@ -1638,8 +1638,8 @@ void Map_RegionXY( float x_min, float y_min, float x_max, float y_max ){ void Map_RegionBounds( const AABB& bounds ){ Map_RegionOff(); - region_mins = vector3_subtracted( bounds.origin, bounds.extents ); - region_maxs = vector3_added( bounds.origin, bounds.extents ); + g_region_mins = vector3_subtracted( bounds.origin, bounds.extents ); + g_region_maxs = vector3_added( bounds.origin, bounds.extents ); deleteSelection(); diff --git a/radiant/map.h b/radiant/map.h index 6e705f6c..10f81d59 100644 --- a/radiant/map.h +++ b/radiant/map.h @@ -95,8 +95,8 @@ scene::Node& Map_FindOrInsertWorldspawn( Map& map ); template class BasicVector3; typedef BasicVector3 Vector3; -extern Vector3 region_mins, region_maxs; -extern bool region_active; +extern Vector3 g_region_mins, g_region_maxs; +extern bool g_region_active; // used to be #defines, multiple engine support suggests we should go towards dynamic extern float g_MaxWorldCoord; diff --git a/radiant/qe3.cpp b/radiant/qe3.cpp index 4bd739ec..e835276d 100644 --- a/radiant/qe3.cpp +++ b/radiant/qe3.cpp @@ -171,7 +171,7 @@ void bsp_init(){ build_set_variable( "BspFile", name.c_str() ); } - if( region_active ){ + if( g_region_active ){ StringOutputStream name( 256 ); name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg"; build_set_variable( "MapFile", name.c_str() ); @@ -240,7 +240,7 @@ bool Region_cameraValid(){ for ( int i = 0 ; i < 3 ; i++ ) { - if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) { + if ( vOrig[i] > g_region_maxs[i] || vOrig[i] < g_region_mins[i] ) { return false; } } @@ -251,7 +251,7 @@ bool Region_cameraValid(){ void RunBSP( const char* name ){ // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 // make sure we don't attempt to region compile a map with the camera outside the region - if ( region_active && !Region_cameraValid() ) { + if ( g_region_active && !Region_cameraValid() ) { globalErrorStream() << "The camera must be in the region to start a region compile.\n"; return; } @@ -267,7 +267,7 @@ void RunBSP( const char* name ){ Map_Snapshot(); } - if ( region_active ) { + if ( g_region_active ) { const char* mapname = Map_Name( g_map ); StringOutputStream name( 256 ); name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg"; diff --git a/radiant/select.cpp b/radiant/select.cpp index f06818d5..d23aaca3 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -868,6 +868,11 @@ void Select_AllOfType(){ } } +void Select_FacesAndPatchesByShader(){ + Scene_BrushFacesSelectByShader( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); + Scene_PatchSelectByShader( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); +} + void Select_Inside( void ){ SelectByBounds::DoSelection(); } @@ -1079,6 +1084,8 @@ void Select_registerCommands(){ GlobalCommands_insert( "RotateSelectionClockwise", FreeCaller() ); GlobalCommands_insert( "RotateSelectionAnticlockwise", FreeCaller() ); + + GlobalCommands_insert( "SelectTextured", FreeCaller(), Accelerator( 'A', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); } diff --git a/radiant/selection.cpp b/radiant/selection.cpp index 2a58b5f1..f76f5e69 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -4080,14 +4080,14 @@ const ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_fa const ButtonIdentifier c_button_texture = c_buttonMiddle; const ModifierFlags c_modifier_apply_texture1 = c_modifierControl | c_modifierShift; -const ModifierFlags c_modifier_apply_texture2 = c_modifierControl; +const ModifierFlags c_modifier_apply_texture2_seamless = c_modifierControl; const ModifierFlags c_modifier_apply_texture3 = c_modifierShift; const ModifierFlags c_modifier_copy_texture = c_modifierNone; void Scene_copyClosestTexture( SelectionTest& test ); -void Scene_applyClosestTexture( SelectionTest& test ); +void Scene_applyClosestTexture( SelectionTest& test, bool seamless ); class TexManipulator_ { @@ -4105,10 +4105,10 @@ void mouseDown( DeviceVector position ){ ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) ); SelectionVolume volume( scissored ); - if ( m_state == c_modifier_apply_texture1 || m_state == c_modifier_apply_texture2 || m_state == c_modifier_apply_texture3 ) { + if ( m_state == c_modifier_apply_texture1 || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) { m_undo_begun = true; GlobalUndoSystem().start(); - Scene_applyClosestTexture( volume ); + Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless ); } else if ( m_state == c_modifier_copy_texture ) { Scene_copyClosestTexture( volume ); @@ -4121,7 +4121,7 @@ void mouseMoved( DeviceVector position ){ ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) ); SelectionVolume volume( scissored ); - Scene_applyClosestTexture( volume ); + Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless ); } } typedef MemberCaller1 MouseMovedCaller; diff --git a/radiant/surfacedialog.cpp b/radiant/surfacedialog.cpp index c73c4d90..1f4ccd92 100644 --- a/radiant/surfacedialog.cpp +++ b/radiant/surfacedialog.cpp @@ -1362,13 +1362,132 @@ void SurfaceInspector::ApplyFlags(){ } +class FaceTexture +{ +public: + TextureProjection m_projection; + ContentsFlagsValue m_flags; + + Plane3 m_plane; + std::size_t m_width; + std::size_t m_height; + + FaceTexture() : m_plane( 0, 0, 1, 0 ), m_width( 64 ), m_height( 64 ) { + } +}; + +FaceTexture g_faceTextureClipboard; + +void FaceTextureClipboard_setDefault(){ + g_faceTextureClipboard.m_flags = ContentsFlagsValue( 0, 0, 0, false ); + TexDef_Construct_Default( g_faceTextureClipboard.m_projection ); +} + +void TextureClipboard_textureSelected( const char* shader ){ + FaceTextureClipboard_setDefault(); +} + + + void Face_getTexture( Face& face, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){ shader = face.GetShader(); face.GetTexdef( projection ); flags = face.getShader().m_flags; + + g_faceTextureClipboard.m_plane = face.getPlane().plane3(); + g_faceTextureClipboard.m_width = face.getShader().width(); + g_faceTextureClipboard.m_height = face.getShader().height(); } typedef Function4 FaceGetTexture; + + +inline bool float_is_largest_absolute( double axis, double other ){ + return fabs( axis ) > fabs( other ); +} + +/// \brief Returns the index of the component of \p v that has the largest absolute value. +inline int vector3_largest_absolute_component_index( const DoubleVector3& v ){ + return ( float_is_largest_absolute( v[1], v[0] ) ) + ? ( float_is_largest_absolute( v[1], v[2] ) ) + ? 1 + : 2 + : ( float_is_largest_absolute( v[0], v[2] ) ) + ? 0 + : 2; +} + +/// \brief Returns the infinite line that is the intersection of \p plane and \p other. +inline DoubleLine plane3_intersect_plane3( const Plane3& plane, const Plane3& other ){ + DoubleLine line; + line.direction = vector3_cross( plane.normal(), other.normal() ); + switch ( vector3_largest_absolute_component_index( line.direction ) ) + { + case 0: + line.origin.x() = 0; + line.origin.y() = ( -other.dist() * plane.normal().z() - -plane.dist() * other.normal().z() ) / line.direction.x(); + line.origin.z() = ( -plane.dist() * other.normal().y() - -other.dist() * plane.normal().y() ) / line.direction.x(); + break; + case 1: + line.origin.x() = ( -plane.dist() * other.normal().z() - -other.dist() * plane.normal().z() ) / line.direction.y(); + line.origin.y() = 0; + line.origin.z() = ( -other.dist() * plane.normal().x() - -plane.dist() * other.normal().x() ) / line.direction.y(); + break; + case 2: + line.origin.x() = ( -other.dist() * plane.normal().y() - -plane.dist() * other.normal().y() ) / line.direction.z(); + line.origin.y() = ( -plane.dist() * other.normal().x() - -other.dist() * plane.normal().x() ) / line.direction.z(); + line.origin.z() = 0; + break; + default: + break; + } + + return line; +} + + +void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ + face.SetShader( shader ); + + DoubleLine line = plane3_intersect_plane3( g_faceTextureClipboard.m_plane, face.getPlane().plane3() ); + Quaternion rotation = Quaternion( vector3_cross( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ), static_cast( 1.0 + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ) ) ); + //Quaternion rotation = quaternion_for_unit_vectors( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ); + //rotation.w() = sqrt( vector3_length_squared( g_faceTextureClipboard.m_plane.normal() ) * vector3_length_squared( face.getPlane().plane3().normal() ) ) + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ); + //globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n"; + //quaternion_normalise( rotation ); + const double n = ( 1.0 / sqrt( rotation[0] * rotation[0] + rotation[1] * rotation[1] + rotation[2] * rotation[2] + rotation[3] * rotation[3] ) ); + rotation = Quaternion( + static_cast( rotation[0] * n ), + static_cast( rotation[1] * n ), + static_cast( rotation[2] * n ), + static_cast( rotation[3] * n ) + ); + //globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n"; + Matrix4 transform = g_matrix4_identity; + matrix4_pivoted_rotate_by_quaternion( transform, rotation, line.origin ); +// Matrix4 transform = matrix4_rotation_for_quaternion_quantised( rotation ); +// Vector3 translation; +// translation_for_pivoted_matrix_transform( translation, transform, line.origin ); +// transform.tx() = translation.x(); +// transform.ty() = translation.y(); +// transform.tz() = translation.z(); + + + //globalOutputStream() << "transform: " << transform << "\n"; + TextureProjection proj = projection; + Texdef_transformLocked( proj, g_faceTextureClipboard.m_width, g_faceTextureClipboard.m_height, g_faceTextureClipboard.m_plane, transform ); + + + //face.SetTexdef( projection ); + face.SetTexdef( proj ); + face.SetFlags( flags ); + + g_faceTextureClipboard.m_plane = face.getPlane().plane3(); + g_faceTextureClipboard.m_projection = proj; +} +typedef Function4 FaceSetTextureSeamless; + + void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ face.SetShader( shader ); face.SetTexdef( projection ); @@ -1400,7 +1519,7 @@ struct Texturable }; -void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable ){ +void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless ){ if ( face.isFiltered() ) { return; } @@ -1409,7 +1528,10 @@ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& be if ( intersection.valid() && SelectionIntersection_closer( intersection, bestIntersection ) ) { bestIntersection = intersection; - texturable.setTexture = makeCallback3( FaceSetTexture(), face ); + if( seamless ) + texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face ); + else + texturable.setTexture = makeCallback3( FaceSetTexture(), face ); texturable.getTexture = makeCallback3( FaceGetTexture(), face ); } } @@ -1439,9 +1561,10 @@ class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker { SelectionTest& m_test; Texturable& m_texturable; +bool m_seamless; mutable SelectionIntersection m_bestIntersection; public: -BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable ) : m_test( test ), m_texturable( texturable ){ +BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ){ } bool pre( const scene::Path& path, scene::Instance& instance ) const { if ( path.top().get().visible() ) { @@ -1451,7 +1574,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) { - Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable ); + Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless ); } } else @@ -1482,9 +1605,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { } }; -Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test ){ +Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false ){ Texturable texturable; - graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable ) ); + graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless ) ); return texturable; } @@ -1497,32 +1620,13 @@ bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedSt return false; } -void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ - Texturable texturable = Scene_getClosestTexturable( graph, test ); +void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless ){ + Texturable texturable = Scene_getClosestTexturable( graph, test, seamless ); if ( texturable.setTexture != SetTextureCallback() ) { texturable.setTexture( shader, projection, flags ); } } - -class FaceTexture -{ -public: -TextureProjection m_projection; -ContentsFlagsValue m_flags; -}; - -FaceTexture g_faceTextureClipboard; - -void FaceTextureClipboard_setDefault(){ - g_faceTextureClipboard.m_flags = ContentsFlagsValue( 0, 0, 0, false ); - TexDef_Construct_Default( g_faceTextureClipboard.m_projection ); -} - -void TextureClipboard_textureSelected( const char* shader ){ - FaceTextureClipboard_setDefault(); -} - class TextureBrowser; extern TextureBrowser g_TextureBrowser; void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const char* shader ); @@ -1535,12 +1639,12 @@ void Scene_copyClosestTexture( SelectionTest& test ){ } } -void Scene_applyClosestTexture( SelectionTest& test ){ +void Scene_applyClosestTexture( SelectionTest& test, bool seamless ){ // UndoableCommand command( "facePaintTexture" ); - Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ); + Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless ); - //SceneChangeNotify(); + SceneChangeNotify(); } diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 33e0fcfe..5902d806 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -2288,10 +2288,10 @@ GtkWidget* TextureBrowser_constructWindow( GtkWindow* toplevel ){ //gtk_menu_bar_append( GTK_MENU_BAR( menu_bar ), tags_item ); GtkButton* button = GTK_BUTTON( gtk_button_new() ); - //button_set_icon( button, "texbro_tags.png" ); - GtkWidget *label = gtk_label_new (">t"); - gtk_container_add (GTK_CONTAINER (button), label); - gtk_widget_show (label); + button_set_icon( button, "texbro_tags.png" ); +// GtkWidget *label = gtk_label_new (">t"); +// gtk_container_add (GTK_CONTAINER (button), label); +// gtk_widget_show (label); gtk_widget_show( GTK_WIDGET( button ) ); gtk_button_set_relief( button, GTK_RELIEF_NONE ); diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 974cda1d..f2a6a52e 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -83,6 +83,7 @@ class ClipPoint { public: Vector3 m_ptClip; // the 3d point +Vector3 m_ptStart; bool m_bSet; ClipPoint(){ @@ -308,15 +309,15 @@ bool ClipMode(){ void NewClipPoint( const Vector3& point ){ if ( g_Clip1.Set() == false ) { - g_Clip1.m_ptClip = point; + g_Clip1.m_ptClip = g_Clip1.m_ptStart = point; g_Clip1.Set( true ); } else if ( g_Clip2.Set() == false ) { - g_Clip2.m_ptClip = point; + g_Clip2.m_ptClip = g_Clip2.m_ptStart = point; g_Clip2.Set( true ); } else if ( g_Clip3.Set() == false ) { - g_Clip3.m_ptClip = point; + g_Clip3.m_ptClip = g_Clip3.m_ptStart = point; g_Clip3.Set( true ); } else @@ -324,7 +325,7 @@ void NewClipPoint( const Vector3& point ){ g_Clip1.Reset(); g_Clip2.Reset(); g_Clip3.Reset(); - g_Clip1.m_ptClip = point; + g_Clip1.m_ptClip = g_Clip1.m_ptStart = point; g_Clip1.Set( true ); } @@ -1000,14 +1001,27 @@ void XYWnd::Clipper_OnLButtonDown( int x, int y ){ void XYWnd::Clipper_OnLButtonUp( int x, int y ){ if ( g_pMovingClip ) { + g_pMovingClip->m_ptStart = g_pMovingClip->m_ptClip; g_pMovingClip = 0; } } -void XYWnd::Clipper_OnMouseMoved( int x, int y ){ +void XYWnd::Clipper_OnMouseMoved( int x, int y, bool snap ){ if ( g_pMovingClip ) { XY_ToPoint( x, y, g_pMovingClip->m_ptClip ); XY_SnapToGrid( g_pMovingClip->m_ptClip ); + if( snap ){ + Vector3 diff = g_pMovingClip->m_ptClip - g_pMovingClip->m_ptStart; + int largest_index = ( fabs( diff[1] ) > fabs( diff[0] ) ) + ? ( fabs( diff[1] ) > fabs( diff[2] ) ) + ? 1 + : 2 + : ( fabs( diff[0] ) > fabs( diff[2] ) ) + ? 0 + : 2; + g_pMovingClip->m_ptClip[( largest_index + 1 ) % 3] = g_pMovingClip->m_ptStart[( largest_index + 1 ) % 3]; + g_pMovingClip->m_ptClip[( largest_index + 2 ) % 3] = g_pMovingClip->m_ptStart[( largest_index + 2 ) % 3]; + } Clip_Update(); } } @@ -1143,7 +1157,7 @@ void XYWnd::NewBrushDrag_End( int x, int y ){ } } -void XYWnd::NewBrushDrag( int x, int y ){ +void XYWnd::NewBrushDrag( int x, int y, bool square ){ Vector3 mins, maxs; XY_ToPoint( m_nNewBrushPressx, m_nNewBrushPressy, mins ); XY_SnapToGrid( mins ); @@ -1159,6 +1173,12 @@ void XYWnd::NewBrushDrag( int x, int y ){ maxs[nDim] = mins[nDim] + GetGridSize(); } + if( square ){ + float squaresize = std::max( fabs( maxs[(nDim + 1) % 3] - mins[(nDim + 1) % 3] ), fabs( maxs[(nDim + 2) % 3] - mins[(nDim + 2) % 3] ) ); + maxs[(nDim + 1) % 3] = ( maxs[(nDim + 1) % 3] - mins[(nDim + 1) % 3] ) > 0.f ? ( mins[(nDim + 1) % 3] + squaresize ) : ( mins[(nDim + 1) % 3] - squaresize ); + maxs[(nDim + 2) % 3] = ( maxs[(nDim + 2) % 3] - mins[(nDim + 2) % 3] ) > 0.f ? ( mins[(nDim + 2) % 3] + squaresize ) : ( mins[(nDim + 2) % 3] - squaresize ); + } + for ( int i = 0 ; i < 3 ; i++ ) { if ( mins[i] == maxs[i] ) { @@ -1520,8 +1540,8 @@ void XYWnd::XY_MouseUp( int x, int y, unsigned int buttons ){ else if ( m_zoom_started ) { Zoom_End(); } - else if ( ( ClipMode() && ( buttons == Clipper_buttons() || buttons == Clipper_quick_buttons() ) ) || - g_clipper_doubleclicked ){ + else if ( ( ClipMode() && ( buttons == Clipper_buttons() || buttons == Clipper_quick_buttons() || g_pMovingClip ) ) || + g_clipper_doubleclicked ){ // handle mouse release, if quit quick clipper mode via doubleclick Clipper_OnLButtonUp( x, y ); g_clipper_doubleclicked = false; } @@ -1548,11 +1568,11 @@ void XYWnd::XY_MouseMoved( int x, int y, unsigned int buttons ){ } else if ( ClipMode() && g_pMovingClip != 0 ) { - Clipper_OnMouseMoved( x, y ); + Clipper_OnMouseMoved( x, y, buttons & RAD_SHIFT ); } // lbutton without selection = drag new brush else if ( m_bNewBrushDrag ) { - NewBrushDrag( x, y ); + NewBrushDrag( x, y, buttons == ( RAD_LBUTTON | RAD_SHIFT ) ); } // control mbutton = move camera @@ -1961,26 +1981,26 @@ void XYWnd::XY_DrawGrid( void ) { const int nDim2 = ( m_viewType == XY ) ? 1 : 2; xb = m_vOrigin[nDim1] - w; - if ( xb < region_mins[nDim1] ) { - xb = region_mins[nDim1]; + if ( xb < g_region_mins[nDim1] ) { + xb = g_region_mins[nDim1]; } xb = step * floor( xb / step ); xe = m_vOrigin[nDim1] + w; - if ( xe > region_maxs[nDim1] ) { - xe = region_maxs[nDim1]; + if ( xe > g_region_maxs[nDim1] ) { + xe = g_region_maxs[nDim1]; } xe = step * ceil( xe / step ); yb = m_vOrigin[nDim2] - h; - if ( yb < region_mins[nDim2] ) { - yb = region_mins[nDim2]; + if ( yb < g_region_mins[nDim2] ) { + yb = g_region_mins[nDim2]; } yb = step * floor( yb / step ); ye = m_vOrigin[nDim2] + h; - if ( ye > region_maxs[nDim2] ) { - ye = region_maxs[nDim2]; + if ( ye > g_region_maxs[nDim2] ) { + ye = g_region_maxs[nDim2]; } ye = step * ceil( ye / step ); @@ -1991,7 +2011,7 @@ void XYWnd::XY_DrawGrid( void ) { // djbob // draw minor blocks - if ( g_xywindow_globals_private.d_showgrid || a < 1.0f ) { + if ( g_xywindow_globals_private.d_showgrid /*|| a < 1.0f*/ ) { if ( a < 1.0f ) { glEnable( GL_BLEND ); } @@ -2036,6 +2056,74 @@ void XYWnd::XY_DrawGrid( void ) { if ( a < 1.0f ) { glDisable( GL_BLEND ); } + + if( g_region_active ){ + float xb_, xe_, yb_, ye_; + + xb_ = m_vOrigin[nDim1] - w; + if ( xb_ < g_MinWorldCoord ) { + xb_ = g_MinWorldCoord; + } + xb_ = step * floor( xb_ / step ); + + xe_ = m_vOrigin[nDim1] + w; + if ( xe_ > g_MaxWorldCoord ) { + xe_ = g_MaxWorldCoord; + } + xe_ = step * ceil( xe_ / step ); + + yb_ = m_vOrigin[nDim2] - h; + if ( yb_ < g_MinWorldCoord ) { + yb_ = g_MinWorldCoord; + } + yb_ = step * floor( yb_ / step ); + + ye_ = m_vOrigin[nDim2] + h; + if ( ye_ > g_MaxWorldCoord ) { + ye_ = g_MaxWorldCoord; + } + ye_ = step * ceil( ye_ / step ); + + glEnable( GL_BLEND ); + // draw minor blocks + if ( COLORS_DIFFER( g_xywindow_globals.color_gridminor, g_xywindow_globals.color_gridback ) ) { + glColor4fv( vector4_to_array( Vector4( g_xywindow_globals.color_gridminor, .5f ) ) ); + + glBegin( GL_LINES ); + int i = 0; + for ( x = xb_ ; x < xe_ ; x += minor_step, ++i ) { + if ( ( i & mask ) != 0 ) { + glVertex2f( x, yb_ ); + glVertex2f( x, ye_ ); + } + } + i = 0; + for ( y = yb_ ; y < ye_ ; y += minor_step, ++i ) { + if ( ( i & mask ) != 0 ) { + glVertex2f( xb_, y ); + glVertex2f( xe_, y ); + } + } + glEnd(); + } + + // draw major blocks + if ( COLORS_DIFFER( g_xywindow_globals.color_gridmajor, g_xywindow_globals.color_gridminor ) ) { + glColor4fv( vector4_to_array( Vector4( g_xywindow_globals.color_gridmajor, .5f ) ) ); + + glBegin( GL_LINES ); + for ( x = xb_ ; x <= xe_ ; x += step ) { + glVertex2f( x, yb_ ); + glVertex2f( x, ye_ ); + } + for ( y = yb_ ; y <= ye_ ; y += step ) { + glVertex2f( xb_, y ); + glVertex2f( xe_, y ); + } + glEnd(); + } + glDisable( GL_BLEND ); + } } // draw coordinate text if needed @@ -2123,26 +2211,26 @@ void XYWnd::XY_DrawBlockGrid(){ int nDim2 = ( m_viewType == XY ) ? 1 : 2; xb = m_vOrigin[nDim1] - w; - if ( xb < region_mins[nDim1] ) { - xb = region_mins[nDim1]; + if ( xb < g_region_mins[nDim1] ) { + xb = g_region_mins[nDim1]; } xb = static_cast( g_xywindow_globals_private.blockSize * floor( xb / g_xywindow_globals_private.blockSize ) ); xe = m_vOrigin[nDim1] + w; - if ( xe > region_maxs[nDim1] ) { - xe = region_maxs[nDim1]; + if ( xe > g_region_maxs[nDim1] ) { + xe = g_region_maxs[nDim1]; } xe = static_cast( g_xywindow_globals_private.blockSize * ceil( xe / g_xywindow_globals_private.blockSize ) ); yb = m_vOrigin[nDim2] - h; - if ( yb < region_mins[nDim2] ) { - yb = region_mins[nDim2]; + if ( yb < g_region_mins[nDim2] ) { + yb = g_region_mins[nDim2]; } yb = static_cast( g_xywindow_globals_private.blockSize * floor( yb / g_xywindow_globals_private.blockSize ) ); ye = m_vOrigin[nDim2] + h; - if ( ye > region_maxs[nDim2] ) { - ye = region_maxs[nDim2]; + if ( ye > g_region_maxs[nDim2] ) { + ye = g_region_maxs[nDim2]; } ye = static_cast( g_xywindow_globals_private.blockSize * ceil( ye / g_xywindow_globals_private.blockSize ) ); diff --git a/radiant/xywindow.h b/radiant/xywindow.h index e1183f50..94be7b3d 100644 --- a/radiant/xywindow.h +++ b/radiant/xywindow.h @@ -118,7 +118,7 @@ void XY_MouseDown( int x, int y, unsigned int buttons ); void XY_MouseMoved( int x, int y, unsigned int buttons ); void NewBrushDrag_Begin( int x, int y ); -void NewBrushDrag( int x, int y ); +void NewBrushDrag( int x, int y, bool square ); void NewBrushDrag_End( int x, int y ); void XY_ToPoint( int x, int y, Vector3& point ); @@ -158,7 +158,7 @@ void UpdateCameraIcon(); void Clipper_OnLButtonDown( int x, int y ); void Clipper_OnLButtonUp( int x, int y ); -void Clipper_OnMouseMoved( int x, int y ); +void Clipper_OnMouseMoved( int x, int y, bool snap ); void Clipper_Crosshair_OnMouseMoved( int x, int y ); void DropClipPoint( int pointx, int pointy ); diff --git a/setup/data/tools/bitmaps/texbro_tags.png b/setup/data/tools/bitmaps/texbro_tags.png new file mode 100644 index 00000000..4107ae91 Binary files /dev/null and b/setup/data/tools/bitmaps/texbro_tags.png differ