X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=radiant%2Fxywindow.cpp;h=3470f861b0834c25f984a62caf646eb0461cea7c;hb=bdd92181b3b41baf91319b5632a5ee85295b3e04;hp=54d121f3907975f9205bcc95a43e5e6f21f7264d;hpb=1b43d194324664a27b2639b326ae55ec996a4c01;p=xonotic%2Fnetradiant.git diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 54d121f3..3470f861 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -58,6 +58,7 @@ #include "gtkutil/widget.h" #include "gtkutil/glwidget.h" #include "gtkutil/filechooser.h" +#include "gtkutil/cursor.h" #include "gtkmisc.h" #include "select.h" #include "csg.h" @@ -348,6 +349,8 @@ struct xywindow_globals_private_t bool m_bChaseMouse; bool m_bSizePaint; + bool g_bCrossHairs; + xywindow_globals_private_t() : d_showgrid( true ), @@ -363,7 +366,9 @@ struct xywindow_globals_private_t m_bCamXYUpdate( true ), m_bChaseMouse( true ), - m_bSizePaint( true ){ + m_bSizePaint( true ), + + g_bCrossHairs( false ){ } }; @@ -496,17 +501,17 @@ void XYWnd::SetScale( float f ){ XYWnd_Update( *this ); } -void XYWnd_ZoomIn( XYWnd* xy ){ +void XYWnd::ZoomIn(){ float max_scale = 64; - float scale = xy->Scale() * 5.0f / 4.0f; + float scale = Scale() * 5.0f / 4.0f; if ( scale > max_scale ) { - if ( xy->Scale() != max_scale ) { - xy->SetScale( max_scale ); + if ( Scale() != max_scale ) { + SetScale( max_scale ); } } else { - xy->SetScale( scale ); + SetScale( scale ); } } @@ -514,17 +519,44 @@ void XYWnd_ZoomIn( XYWnd* xy ){ // NOTE: the zoom out factor is 4/5, we could think about customizing it // we don't go below a zoom factor corresponding to 10% of the max world size // (this has to be computed against the window size) -void XYWnd_ZoomOut( XYWnd* xy ){ - float min_scale = MIN( xy->Width(),xy->Height() ) / ( 1.1f * ( g_MaxWorldCoord - g_MinWorldCoord ) ); - float scale = xy->Scale() * 4.0f / 5.0f; +void XYWnd::ZoomOut(){ + float min_scale = MIN( Width(), Height() ) / ( 1.1f * ( g_MaxWorldCoord - g_MinWorldCoord ) ); + float scale = Scale() * 4.0f / 5.0f; if ( scale < min_scale ) { - if ( xy->Scale() != min_scale ) { - xy->SetScale( min_scale ); + if ( Scale() != min_scale ) { + SetScale( min_scale ); } } else { - xy->SetScale( scale ); + SetScale( scale ); + } +} + +void XYWnd::ZoomInWithMouse( int pointx, int pointy ){ + float old_scale = Scale(); + ZoomIn(); + if ( g_xywindow_globals.m_bImprovedWheelZoom ) { + float scale_diff = 1.0 / old_scale - 1.0 / Scale(); + int nDim1 = ( m_viewType == YZ ) ? 1 : 0; + int nDim2 = ( m_viewType == XY ) ? 1 : 2; + Vector3 origin = GetOrigin(); + origin[nDim1] += scale_diff * (pointx - 0.5 * Width()); + origin[nDim2] -= scale_diff * (pointy - 0.5 * Height()); + SetOrigin( origin ); + } +} + +void XYWnd::Redraw() { + if ( glwidget_make_current( m_gl_widget ) != FALSE ) { + if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { + GlobalOpenGL_debugAssertNoErrors(); + XY_Draw(); + GlobalOpenGL_debugAssertNoErrors(); + + m_XORRectangle.set( rectangle_t() ); + } + glwidget_swap_buffers( m_gl_widget ); } } @@ -537,8 +569,6 @@ VIEWTYPE GlobalXYWnd_getCurrentViewType(){ // ============================================================================= // variables -bool g_bCrossHairs = false; - ui::Menu XYWnd::m_mnuDrop(ui::null); // this is disabled, and broken @@ -709,7 +739,16 @@ Shader* XYWnd::m_state_selected = 0; void xy_update_xor_rectangle( XYWnd& self, rect_t area ){ if ( self.GetWidget().visible() ) { - self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.Width(), self.Height() ) ); + rectangle_t rect = rectangle_from_area( area.min, area.max, self.Width(), self.Height() ); + int nDim1 = ( self.GetViewType() == YZ ) ? 1 : 0; + int nDim2 = ( self.GetViewType() == XY ) ? 1 : 2; + rect.x /= self.Scale(); + rect.y /= self.Scale(); + rect.w /= self.Scale(); + rect.h /= self.Scale(); + rect.x += self.GetOrigin()[nDim1]; + rect.y += self.GetOrigin()[nDim2]; + self.m_XORRectangle.set( rect ); } } @@ -751,10 +790,10 @@ void xywnd_motion( gdouble x, gdouble y, guint state, void* data ){ gboolean xywnd_wheel_scroll( ui::Widget widget, GdkEventScroll* event, XYWnd* xywnd ){ if ( event->direction == GDK_SCROLL_UP ) { - XYWnd_ZoomIn( xywnd ); + xywnd->ZoomInWithMouse( (int)event->x, (int)event->y ); } else if ( event->direction == GDK_SCROLL_DOWN ) { - XYWnd_ZoomOut( xywnd ); + xywnd->ZoomOut(); } return FALSE; } @@ -768,20 +807,10 @@ gboolean xywnd_size_allocate( ui::Widget widget, GtkAllocation* allocation, XYWn } gboolean xywnd_expose( ui::Widget widget, GdkEventExpose* event, XYWnd* xywnd ){ - if ( glwidget_make_current( xywnd->GetWidget() ) != FALSE ) { - if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { - GlobalOpenGL_debugAssertNoErrors(); - xywnd->XY_Draw(); - GlobalOpenGL_debugAssertNoErrors(); - - xywnd->m_XORRectangle.set( rectangle_t() ); - } - glwidget_swap_buffers( xywnd->GetWidget() ); - } + xywnd->Redraw(); return FALSE; } - void XYWnd_CameraMoved( XYWnd& xywnd ){ if ( g_xywindow_globals_private.m_bCamXYUpdate ) { XYWnd_Update( xywnd ); @@ -795,7 +824,8 @@ XYWnd::XYWnd() : m_parent( ui::null ), m_window_observer( NewWindowObserver() ), m_XORRectangle( m_gl_widget ), - m_chasemouse_handler( 0 ){ + m_chasemouse_handler( 0 ) { + m_bActive = false; m_buttonstate = 0; @@ -846,8 +876,11 @@ XYWnd::XYWnd() : Map_addValidCallback( g_map, DeferredDrawOnMapValidChangedCaller( m_deferredDraw ) ); - updateProjection(); - updateModelview(); + // This reconstruct=false argument is used to avoid a circular dependency + // between modelview and projection initialization and a valgrind complaint + updateProjection( false ); + updateModelview( false ); + m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); AddSceneChangeCallback( ReferenceCaller( *this ) ); AddCameraMovedCallback( ReferenceCaller( *this ) ); @@ -945,14 +978,11 @@ void XYWnd::Clipper_Crosshair_OnMouseMoved( int x, int y ){ Vector3 mousePosition; XY_ToPoint( x, y, mousePosition ); if ( ClipMode() && GlobalClipPoints_Find( mousePosition, (VIEWTYPE)m_viewType, m_fScale ) != 0 ) { - GdkCursor *cursor; - cursor = gdk_cursor_new( GDK_CROSSHAIR ); - gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), cursor ); - gdk_cursor_unref( cursor ); + set_cursor ( m_gl_widget, GDK_CROSSHAIR ); } else { - gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), 0 ); + default_cursor( m_gl_widget ); } } @@ -1069,11 +1099,11 @@ void entitycreate_activated( ui::Widget item ){ g_pParentWnd->ActiveXY()->OnEntityCreate( entity_name ); } else { - GlobalRadiant().m_pfnMessageBox( MainFrame_getWindow(), "There's already a worldspawn in your map!" - "", - "Info", - eMB_OK, - eMB_ICONDEFAULT ); + GlobalRadiant().m_pfnMessageBox( MainFrame_getWindow(), + "There's already a worldspawn in your map!", + "Info", + eMB_OK, + eMB_ICONDEFAULT ); } } @@ -1185,13 +1215,13 @@ void XYWnd::Move_Begin(){ Move_End(); } m_move_started = true; - g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), XYWnd_moveDelta, this ); + g_xywnd_freezePointer.freeze_pointer( m_gl_widget, XYWnd_moveDelta, this ); m_move_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Move_focusOut ), this ); } void XYWnd::Move_End(){ m_move_started = false; - g_xywnd_freezePointer.unfreeze_pointer( m_parent ? m_parent : MainFrame_getWindow() ); + g_xywnd_freezePointer.unfreeze_pointer( m_gl_widget ); g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_move_focusOut ); } @@ -1204,16 +1234,15 @@ int g_dragZoom = 0; void XYWnd_zoomDelta( int x, int y, unsigned int state, void* data ){ if ( y != 0 ) { g_dragZoom += y; - while ( abs( g_dragZoom ) > 8 ) { if ( g_dragZoom > 0 ) { - XYWnd_ZoomOut( reinterpret_cast( data ) ); + reinterpret_cast( data )->ZoomOut(); g_dragZoom -= 8; } else { - XYWnd_ZoomIn( reinterpret_cast( data ) ); + reinterpret_cast( data )->ZoomIn(); g_dragZoom += 8; } } @@ -1360,7 +1389,7 @@ void XYWnd::XY_MouseMoved( int x, int y, unsigned int buttons ){ << " z:: " << FloatFormat( m_mousePosition[2], 6, 1 ); g_pParentWnd->SetStatusText( g_pParentWnd->m_position_status, status.c_str() ); - if ( g_bCrossHairs ) { + if ( g_xywindow_globals_private.g_bCrossHairs ) { XYWnd_Update( *this ); } @@ -1487,17 +1516,25 @@ void XYWnd::XY_DisableBackground( void ){ void WXY_BackgroundSelect( void ){ bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0; + + ui::Window main_window = MainFrame_getWindow(); + if ( !brushesSelected ) { - ui::alert( ui::root, "You have to select some brushes to get the bounding box for.\n", + ui::alert( main_window, "You have to select some brushes to get the bounding box for.\n", "No selection", ui::alert_type::OK, ui::alert_icon::Error ); return; } - const char *filename = MainFrame_getWindow().file_dialog( TRUE, "Background Image", NULL, NULL ); + const char *filename = main_window.file_dialog( TRUE, "Background Image", NULL, NULL ); + g_pParentWnd->ActiveXY()->XY_DisableBackground(); + if ( filename ) { g_pParentWnd->ActiveXY()->XY_LoadBackgroundImage( filename ); } + + // Draw the background image immediately (do not wait for user input). + g_pParentWnd->ActiveXY()->Redraw(); } /* @@ -2101,7 +2138,7 @@ RenderStateFlags m_globalstate; Shader* m_state_selected; }; -void XYWnd::updateProjection(){ +void XYWnd::updateProjection( bool reconstruct ){ m_projection[0] = 1.0f / static_cast( m_nWidth / 2 ); m_projection[5] = 1.0f / static_cast( m_nHeight / 2 ); m_projection[10] = 1.0f / ( g_MaxWorldCoord * m_fScale ); @@ -2124,11 +2161,13 @@ void XYWnd::updateProjection(){ m_projection[15] = 1.0f; - m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); + if (reconstruct) { + m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); + } } // note: modelview matrix must have a uniform scale, otherwise strange things happen when rendering the rotation manipulator. -void XYWnd::updateModelview(){ +void XYWnd::updateModelview( bool reconstruct ){ int nDim1 = ( m_viewType == YZ ) ? 1 : 0; int nDim2 = ( m_viewType == XY ) ? 1 : 2; @@ -2184,7 +2223,9 @@ void XYWnd::updateModelview(){ m_modelview[3] = m_modelview[7] = m_modelview[11] = 0; m_modelview[15] = 1; - m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); + if (reconstruct) { + m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); + } } /* @@ -2294,7 +2335,7 @@ void XYWnd::XY_Draw(){ PaintSizeInfo( nDim1, nDim2, min, max ); } - if ( g_bCrossHairs ) { + if ( g_xywindow_globals_private.g_bCrossHairs ) { glColor4f( 0.2f, 0.9f, 0.2f, 0.8f ); glBegin( GL_LINES ); if ( m_viewType == XY ) { @@ -2511,20 +2552,20 @@ void XY_Zoom100(){ } void XY_ZoomIn(){ - XYWnd_ZoomIn( g_pParentWnd->ActiveXY() ); + g_pParentWnd->ActiveXY()->ZoomIn(); } // NOTE: the zoom out factor is 4/5, we could think about customizing it // we don't go below a zoom factor corresponding to 10% of the max world size // (this has to be computed against the window size) void XY_ZoomOut(){ - XYWnd_ZoomOut( g_pParentWnd->ActiveXY() ); + g_pParentWnd->ActiveXY()->ZoomOut(); } void ToggleShowCrosshair(){ - g_bCrossHairs ^= 1; + g_xywindow_globals_private.g_bCrossHairs ^= 1; XY_UpdateAllWindows(); } @@ -2758,8 +2799,10 @@ void XYWindow_Construct(){ GlobalPreferenceSystem().registerPreference( "ClipCaulk", make_property_string( g_clip_useCaulk ) ); GlobalPreferenceSystem().registerPreference( "NewRightClick", make_property_string( g_xywindow_globals.m_bRightClick ) ); + GlobalPreferenceSystem().registerPreference( "ImprovedWheelZoom", make_property_string( g_xywindow_globals.m_bImprovedWheelZoom ) ); GlobalPreferenceSystem().registerPreference( "ChaseMouse", make_property_string( g_xywindow_globals_private.m_bChaseMouse ) ); GlobalPreferenceSystem().registerPreference( "SizePainting", make_property_string( g_xywindow_globals_private.m_bSizePaint ) ); + GlobalPreferenceSystem().registerPreference( "ShowCrosshair", make_property_string( g_xywindow_globals_private.g_bCrossHairs ) ); GlobalPreferenceSystem().registerPreference( "NoStipple", make_property_string( g_xywindow_globals.m_bNoStipple ) ); GlobalPreferenceSystem().registerPreference( "SI_ShowCoords", make_property_string( g_xywindow_globals_private.show_coordinates ) ); GlobalPreferenceSystem().registerPreference( "SI_ShowOutlines", make_property_string( g_xywindow_globals_private.show_outline ) );