From 6eee961fcce880b56c3863260b58f12fc3eef7b3 Mon Sep 17 00:00:00 2001 From: Garux Date: Wed, 2 Aug 2017 09:53:07 +0300 Subject: [PATCH] Radiant: binds... * shift + m3: apply texture name and alignment to selected primitives and faces (m3 was inconsistent + often required quite deep planning) * ctrl + shift + m3: also project tex from face to selection misc... * lazy cursor updates in clipper mode * update cursor immediately on clipper mode toggles * fixes and optimizations of entity names rendering; for instance: don't prerender textures for unneeded names FBO overlay fixes --- include/cullable.h | 3 + libs/gtkutil/xorrectangle.h | 11 ++- plugins/entity/doom3group.cpp | 15 +-- plugins/entity/group.cpp | 15 +-- plugins/entity/light.cpp | 9 +- plugins/entity/miscmodel.cpp | 9 +- plugins/entity/namedentity.h | 45 +++++---- radiant/brushmanip.cpp | 22 +++++ radiant/brushmanip.h | 2 + radiant/camwindow.cpp | 11 +-- radiant/patchmanip.cpp | 17 ++++ radiant/patchmanip.h | 2 + radiant/select.cpp | 10 ++ radiant/select.h | 1 + radiant/selection.cpp | 6 +- radiant/surfacedialog.cpp | 19 +++- radiant/xywindow.cpp | 168 +++++++++++++++++++--------------- radiant/xywindow.h | 5 + 18 files changed, 239 insertions(+), 131 deletions(-) diff --git a/include/cullable.h b/include/cullable.h index 299af2e2..7281fd01 100644 --- a/include/cullable.h +++ b/include/cullable.h @@ -57,6 +57,9 @@ virtual bool fill() const = 0; virtual const Matrix4& GetViewport() const = 0; virtual const Matrix4& GetProjection() const = 0; virtual const Matrix4& GetModelview() const = 0; + +virtual const Matrix4& GetViewMatrix() const = 0; //viewproj +virtual const Vector3& getViewer() const = 0; }; class Cullable diff --git a/libs/gtkutil/xorrectangle.h b/libs/gtkutil/xorrectangle.h index abb5bf19..01b0b34c 100644 --- a/libs/gtkutil/xorrectangle.h +++ b/libs/gtkutil/xorrectangle.h @@ -73,10 +73,19 @@ public: } ~XORRectangle() { } - void set( rectangle_t rectangle ) { + void set( rectangle_t rectangle, int width, int height ) { if( rectangle.w != 0.f && rectangle.h != 0.f ) { GlobalOpenGL_debugAssertNoErrors(); + glViewport( 0, 0, width, height ); + // set up viewpoint + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glOrtho( 0, width, 0, height, -100, 100 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glDisable( GL_DEPTH_TEST ); glDisable( GL_TEXTURE_2D ); diff --git a/plugins/entity/doom3group.cpp b/plugins/entity/doom3group.cpp index 099c7d4c..68c8b783 100644 --- a/plugins/entity/doom3group.cpp +++ b/plugins/entity/doom3group.cpp @@ -69,6 +69,8 @@ inline void PointVertexArray_testSelect( PointVertex* first, std::size_t count, ); } +const char EXCLUDE_NAME[] = "worldspawn"; + class Doom3Group : public Bounded, public Snappable @@ -260,7 +262,7 @@ Doom3Group( EntityClass* eclass, scene::Node& node, const Callback& transformCha m_nameKeys( m_entity ), m_funcStaticOrigin( m_traverse, m_origin ), m_name_origin( g_vector3_identity ), - m_renderName( m_named, m_name_origin ), + m_renderName( m_named, m_name_origin, EXCLUDE_NAME ), m_skin( SkinChangedCaller( *this ) ), m_curveNURBS( boundsChanged ), m_curveCatmullRom( boundsChanged ), @@ -279,7 +281,7 @@ Doom3Group( const Doom3Group& other, scene::Node& node, const Callback& transfor m_nameKeys( m_entity ), m_funcStaticOrigin( m_traverse, m_origin ), m_name_origin( g_vector3_identity ), - m_renderName( m_named, m_name_origin ), + m_renderName( m_named, m_name_origin, EXCLUDE_NAME ), m_skin( SkinChangedCaller( *this ) ), m_curveNURBS( boundsChanged ), m_curveCatmullRom( boundsChanged ), @@ -363,13 +365,14 @@ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& l renderer.addRenderable( m_curveCatmullRom.m_renderCurve, localToWorld ); } - if ( selected || childSelected || ( g_showNames && ( volume.fill() || aabb_fits_view( childBounds, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) { + if ( m_renderName.excluded_not() + && ( selected || childSelected || ( g_showNames && ( volume.fill() || aabb_fits_view( childBounds, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) ) { // draw models as usual if ( !isModel() ) { // don't draw the name for worldspawn - if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { - return; - } +// if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { +// return; +// } // place name in the middle of the "children cloud" m_name_origin = childBounds.origin; diff --git a/plugins/entity/group.cpp b/plugins/entity/group.cpp index 78d507a2..ad34ccb0 100644 --- a/plugins/entity/group.cpp +++ b/plugins/entity/group.cpp @@ -49,6 +49,8 @@ /// The "origin" key directly controls the entity's local-to-parent transform. +const char EXCLUDE_NAME[] = "worldspawn"; + class Group { EntityKeyValues m_entity; @@ -84,7 +86,7 @@ Group( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, m_originKey( OriginChangedCaller( *this ) ), m_origin( ORIGINKEY_IDENTITY ), m_name_origin( g_vector3_identity ), - m_renderName( m_named, m_name_origin ), + m_renderName( m_named, m_name_origin, EXCLUDE_NAME ), m_transformChanged( transformChanged ), m_evaluateTransform( evaluateTransform ){ construct(); @@ -97,7 +99,7 @@ Group( const Group& other, scene::Node& node, const Callback& transformChanged, m_originKey( OriginChangedCaller( *this ) ), m_origin( ORIGINKEY_IDENTITY ), m_name_origin( g_vector3_identity ), - m_renderName( m_named, m_name_origin ), + m_renderName( m_named, m_name_origin, EXCLUDE_NAME ), m_transformChanged( transformChanged ), m_evaluateTransform( evaluateTransform ){ construct(); @@ -150,11 +152,12 @@ void detach( scene::Traversable::Observer* observer ){ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected, const AABB& childBounds ) const { renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - if ( selected || childSelected || ( g_showNames && ( volume.fill() || aabb_fits_view( childBounds, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) { + if ( m_renderName.excluded_not() + && ( selected || childSelected || ( g_showNames && ( volume.fill() || aabb_fits_view( childBounds, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) ) { // don't draw the name for worldspawn - if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { - return; - } +// if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { +// return; +// } // place name in the middle of the "children cloud" m_name_origin = childBounds.origin; diff --git a/plugins/entity/light.cpp b/plugins/entity/light.cpp index 91ca3ba9..966b0d58 100644 --- a/plugins/entity/light.cpp +++ b/plugins/entity/light.cpp @@ -1066,6 +1066,8 @@ inline Matrix4 matrix4_from_planes( const Plane3& left, const Plane3& right, con ); } +const char EXCLUDE_NAME[] = "light"; + class Light : public OpenGLRenderable, public Cullable, @@ -1306,7 +1308,7 @@ Light( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, m_radii_fill( m_radii, m_aabb_light.origin ), m_radii_box( m_aabb_light.origin ), m_render_center( m_doom3Radius.m_center, m_entity.getEntityClass() ), - m_renderName( m_named, m_aabb_light.origin ), + m_renderName( m_named, m_aabb_light.origin, EXCLUDE_NAME ), m_useLightOrigin( false ), m_useLightRotation( false ), m_renderProjection( m_doom3Projection ), @@ -1330,7 +1332,7 @@ Light( const Light& other, scene::Node& node, const Callback& transformChanged, m_radii_fill( m_radii, m_aabb_light.origin ), m_radii_box( m_aabb_light.origin ), m_render_center( m_doom3Radius.m_center, m_entity.getEntityClass() ), - m_renderName( m_named, m_aabb_light.origin ), + m_renderName( m_named, m_aabb_light.origin, EXCLUDE_NAME ), m_useLightOrigin( false ), m_useLightRotation( false ), m_renderProjection( m_doom3Projection ), @@ -1460,7 +1462,8 @@ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& l } } - if ( ( selected || ( g_showNames && ( volume.fill() || aabb_fits_view( m_aabb_light, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) && !string_equal( m_named.name(), "light" ) ) { + if ( m_renderName.excluded_not() + && ( selected || ( g_showNames && ( volume.fill() || aabb_fits_view( m_aabb_light, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) ) { m_renderName.render( renderer, volume, localToWorld, selected ); } } diff --git a/plugins/entity/miscmodel.cpp b/plugins/entity/miscmodel.cpp index 302542c6..9e65fe3d 100644 --- a/plugins/entity/miscmodel.cpp +++ b/plugins/entity/miscmodel.cpp @@ -50,6 +50,8 @@ #include "entity.h" +const char EXCLUDE_NAME[] = "misc_model"; + class MiscModel : public Snappable { @@ -125,7 +127,7 @@ MiscModel( EntityClass* eclass, scene::Node& node, const Callback& transformChan m_filter( m_entity, node ), m_named( m_entity ), m_nameKeys( m_entity ), - m_renderName( m_named, g_vector3_identity ), + m_renderName( m_named, g_vector3_identity, EXCLUDE_NAME ), m_transformChanged( transformChanged ), m_evaluateTransform( evaluateTransform ){ construct(); @@ -141,7 +143,7 @@ MiscModel( const MiscModel& other, scene::Node& node, const Callback& transformC m_filter( m_entity, node ), m_named( m_entity ), m_nameKeys( m_entity ), - m_renderName( m_named, g_vector3_identity ), + m_renderName( m_named, g_vector3_identity, EXCLUDE_NAME ), m_transformChanged( transformChanged ), m_evaluateTransform( evaluateTransform ){ construct(); @@ -195,7 +197,8 @@ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& l m_renderOrigin.render( renderer, volume, localToWorld ); } renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - if ( ( selected || ( g_showNames && ( volume.fill() || aabb_fits_view( AABB( Vector3( 0, 0, 0 ), Vector3( 32, 32, 32 ) ), volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) && !string_equal( m_named.name(), "misc_model" ) ) { + if ( m_renderName.excluded_not() + && ( selected || ( g_showNames && ( volume.fill() || aabb_fits_view( AABB( Vector3( 0, 0, 0 ), Vector3( 32, 32, 32 ) ), volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) ) { m_renderName.render( renderer, volume, localToWorld, selected ); } } diff --git a/plugins/entity/namedentity.h b/plugins/entity/namedentity.h index c0a9a56c..69d3c091 100644 --- a/plugins/entity/namedentity.h +++ b/plugins/entity/namedentity.h @@ -91,8 +91,9 @@ typedef MemberCaller1 #include "renderable.h" -#include "pivot.h" -#include "math/frustum.h" +//#include "pivot.h" +//#include "math/frustum.h" +#include "cullable.h" class RenderableNamedEntity : public OpenGLRenderable { enum ENameMode{ @@ -108,18 +109,24 @@ class RenderableNamedEntity : public OpenGLRenderable { int m_width; int m_height; mutable float m_screenPos[2]; + const char* m_exclude; public: typedef Static StaticShader; static Shader* getShader() { return StaticShader::instance(); } - RenderableNamedEntity( NamedEntity& named, const Vector3& position ) - : m_named( named ), m_position( position ), m_tex( 0 ) { + RenderableNamedEntity( NamedEntity& named, const Vector3& position, const char* exclude = 0 ) + : m_named( named ), m_position( position ), m_tex( 0 ), m_exclude( exclude ) { construct_textures( g_showTargetNames ? m_named.name() : m_named.classname() ); m_named.attach( IdentifierChangedCaller( *this ) ); } + bool excluded_not() const { + return m_tex > 0; + } private: void construct_textures( const char* name ){ + if( m_exclude && string_equal( m_exclude, name ) ) + return; glGenTextures( 1, &m_tex ); if( m_tex > 0 ) { unsigned int colour[3]; @@ -173,28 +180,27 @@ public: void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected = false ) const{ setMode( selected, childSelected ); - if( m_nameMode == eNameNormal && volume.fill() ){ + if( volume.fill() ){ // globalOutputStream() << localToWorld << " localToWorld\n"; // globalOutputStream() << volume.GetModelview() << " modelview\n"; // globalOutputStream() << volume.GetProjection() << " Projection\n"; // globalOutputStream() << volume.GetViewport() << " Viewport\n"; - Matrix4 viewproj = matrix4_multiplied_by_matrix4( volume.GetProjection(), volume.GetModelview() ); - Vector3 viewer = vector4_to_vector3( viewer_from_viewproj( viewproj ) ); - Vector3 pos_in_world = matrix4_transformed_point( localToWorld, m_position ); - if( vector3_length_squared( pos_in_world - viewer ) > g_showNamesDist * g_showNamesDist ){ + //Matrix4 viewproj = matrix4_multiplied_by_matrix4( volume.GetProjection(), volume.GetModelview() ); + const Matrix4& viewproj = volume.GetViewMatrix(); + //Vector3 viewer = vector4_to_vector3( viewer_from_viewproj( viewproj ) ); + const Vector3 pos_in_world = matrix4_transformed_point( localToWorld, m_position ); + if( viewproj[3] * pos_in_world[0] + viewproj[7] * pos_in_world[1] + viewproj[11] * pos_in_world[2] + viewproj[15] < 3e-5 ) //z < 0: behind nearplane return; - } + if( m_nameMode == eNameNormal && vector3_length_squared( pos_in_world - volume.getViewer() ) > static_cast( g_showNamesDist ) * static_cast( g_showNamesDist ) ) + return; + //globalOutputStream() << viewer[0] << " " << viewer[1] << " " << viewer[2] << " Viewer\n"; - //globalOutputStream() << pos_in_world[0] << " " << pos_in_world[1] << " " << pos_in_world[2] << " position\n"; - //globalOutputStream() << m_position[0] << " " << m_position[1] << " " << m_position[2] << " position\n"; + //globalOutputStream() << m_position[0] << " " << m_position[1] << " " << m_position[2] << " m_position\n"; + //globalOutputStream() << pos_in_world[0] << " " << pos_in_world[1] << " " << pos_in_world[2] << " pos_in_world\n"; } - Vector4 position; - position[0] = m_position[0]; - position[1] = m_position[1]; - position[2] = m_position[2]; - position[3] = 1.f; + Vector4 position( m_position, 1.f ); #if 0 // globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " position\n"; @@ -212,8 +218,9 @@ public: // globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " Viewport\n"; #else - Matrix4 object2screen = volume.GetProjection(); - matrix4_multiply_by_matrix4( object2screen, volume.GetModelview() ); + //Matrix4 object2screen = volume.GetProjection(); + Matrix4 object2screen( volume.GetViewMatrix() ); + //matrix4_multiply_by_matrix4( object2screen, volume.GetModelview() ); matrix4_multiply_by_matrix4( object2screen, localToWorld ); // globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " position\n"; matrix4_transform_vector4( object2screen, position ); diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index 861ad4fc..fc036534 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -757,6 +757,28 @@ void Scene_BrushProjectTexture_Component_Selected( scene::Graph& graph, const te SceneChangeNotify(); } +class FaceProjectTexture_fromFace +{ + const TextureProjection& m_projection; + const Vector3& m_normal; +public: + FaceProjectTexture_fromFace( const TextureProjection& projection, const Vector3& normal ) : m_projection( projection ), m_normal( normal ) { + } + void operator()( Face& face ) const { + face.ProjectTexture( m_projection, m_normal ); + } +}; + +void Scene_BrushProjectTexture_Selected( scene::Graph& graph, const TextureProjection& projection, const Vector3& normal ){ + Scene_ForEachSelectedBrush_ForEachFace( graph, FaceProjectTexture_fromFace( projection, normal ) ); + SceneChangeNotify(); +} + +void Scene_BrushProjectTexture_Component_Selected( scene::Graph& graph, const TextureProjection& projection, const Vector3& normal ){ + Scene_ForEachSelectedBrushFace( graph, FaceProjectTexture_fromFace( projection, normal ) ); + SceneChangeNotify(); +} + class FaceFitTexture { diff --git a/radiant/brushmanip.h b/radiant/brushmanip.h index ced6caf8..21fbfd1e 100644 --- a/radiant/brushmanip.h +++ b/radiant/brushmanip.h @@ -80,6 +80,8 @@ template class BasicVector3; typedef BasicVector3 Vector3; void Scene_BrushProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ); void Scene_BrushProjectTexture_Component_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ); +void Scene_BrushProjectTexture_Selected( scene::Graph& graph, const TextureProjection& projection, const Vector3& normal ); +void Scene_BrushProjectTexture_Component_Selected( scene::Graph& graph, const TextureProjection& projection, const Vector3& normal ); void Scene_BrushFitTexture_Selected( scene::Graph& graph, float s_repeat, float t_repeat ); void Scene_BrushFitTexture_Component_Selected( scene::Graph& graph, float s_repeat, float t_repeat ); diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index a10489e3..0beb2ed7 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -950,16 +950,7 @@ void camwnd_update_xor_rectangle( CamWnd& self, rect_t area ){ glDrawBuffer( GL_FRONT ); self.m_fbo->blit(); - glViewport( 0, 0, self.getCamera().width, self.getCamera().height ); - // set up viewpoint - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0, self.getCamera().width, 0, self.getCamera().height, -100, 100 ); - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.getCamera().width, self.getCamera().height ) ); + self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.getCamera().width, self.getCamera().height ), self.getCamera().width, self.getCamera().height ); glDrawBuffer( GL_BACK ); diff --git a/radiant/patchmanip.cpp b/radiant/patchmanip.cpp index 46089fdd..86a167b9 100644 --- a/radiant/patchmanip.cpp +++ b/radiant/patchmanip.cpp @@ -319,6 +319,23 @@ void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& te SceneChangeNotify(); } +class PatchProjectTexture_fromFace +{ + const TextureProjection& m_projection; + const Vector3& m_normal; +public: + PatchProjectTexture_fromFace( const TextureProjection& projection, const Vector3& normal ) : m_projection( projection ), m_normal( normal ) { + } + void operator()( Patch& patch ) const { + patch.ProjectTexture( m_projection, m_normal ); + } +}; + +void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const TextureProjection& projection, const Vector3& normal ){ + Scene_forEachVisibleSelectedPatch( PatchProjectTexture_fromFace( projection, normal ) ); + SceneChangeNotify(); +} + class PatchFlipTexture { int m_axis; diff --git a/radiant/patchmanip.h b/radiant/patchmanip.h index c97fc61e..7493fc7d 100644 --- a/radiant/patchmanip.h +++ b/radiant/patchmanip.h @@ -46,6 +46,8 @@ class texdef_t; template class BasicVector3; typedef BasicVector3 Vector3; void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ); +class TextureProjection; +void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const TextureProjection& projection, const Vector3& normal ); void Scene_PatchNaturalTexture_Selected( scene::Graph& graph ); void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t ); diff --git a/radiant/select.cpp b/radiant/select.cpp index 20eccbab..92398b93 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -898,6 +898,16 @@ void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ){ SceneChangeNotify(); } +void Select_ProjectTexture( const TextureProjection& projection, const Vector3& normal ){ + if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { + Scene_BrushProjectTexture_Selected( GlobalSceneGraph(), projection, normal ); + Scene_PatchProjectTexture_Selected( GlobalSceneGraph(), projection, normal ); + } + Scene_BrushProjectTexture_Component_Selected( GlobalSceneGraph(), projection, normal ); + + SceneChangeNotify(); +} + void Select_FitTexture( float horizontal, float vertical ){ if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { Scene_BrushFitTexture_Selected( GlobalSceneGraph(), horizontal, vertical ); diff --git a/radiant/select.h b/radiant/select.h index 486264b1..16e3050b 100644 --- a/radiant/select.h +++ b/radiant/select.h @@ -69,6 +69,7 @@ void Select_ScaleTexture( float x, float y ); void Select_ShiftTexture( float x, float y ); class texdef_t; void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ); +void Select_ProjectTexture( const TextureProjection& projection, const Vector3& normal ); void Select_FitTexture( float horizontal = 1, float vertical = 1 ); void FindReplaceTextures( const char* pFind, const char* pReplace, bool bSelected ); diff --git a/radiant/selection.cpp b/radiant/selection.cpp index 9d2b412c..2de51ace 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -4100,7 +4100,7 @@ const ModifierFlags c_modifier_copy_texture = c_modifierNone; void Scene_copyClosestTexture( SelectionTest& test ); -void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project ); +void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project, bool texturize_selected = false ); void Scene_projectClosestTexture( SelectionTest& test ); class TexManipulator_ @@ -4122,7 +4122,7 @@ void mouseDown( DeviceVector position ){ if ( m_state == c_modifier_apply_texture1_project || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) { m_undo_begun = true; GlobalUndoSystem().start(); - Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project ); + Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project, true ); } else if ( m_state == c_modifier_copy_texture ) { Scene_copyClosestTexture( volume ); @@ -4142,7 +4142,7 @@ typedef MemberCaller1GetXYWnd() ){ + g_pParentWnd->GetXYWnd()->CursorSet( cursor ); + } + if( g_pParentWnd->GetXZWnd() ){ + g_pParentWnd->GetXZWnd()->CursorSet( cursor ); + } + if( g_pParentWnd->GetYZWnd() ){ + g_pParentWnd->GetYZWnd()->CursorSet( cursor ); + } + } + Clip_Update(); } @@ -746,34 +762,31 @@ bool XYWnd::chaseMouseMotion( int pointx, int pointy ){ // XYWnd class Shader* XYWnd::m_state_selected = 0; -void xy_update_xor_rectangle( XYWnd& self, rect_t area ){ - if ( GTK_WIDGET_VISIBLE( self.GetWidget() ) ) { - if ( glwidget_make_current( self.GetWidget() ) != FALSE ) { +bool XYWnd::XY_Draw_Overlay_start(){ + if ( GTK_WIDGET_VISIBLE( m_gl_widget ) ) { + if ( glwidget_make_current( m_gl_widget ) != FALSE ) { if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { GlobalOpenGL_debugAssertNoErrors(); - glDrawBuffer( GL_FRONT ); - self.m_fbo->blit(); - - glViewport( 0, 0, self.Width(), self.Height() ); - // set up viewpoint - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0, self.Width(), 0, self.Height(), -100, 100 ); - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - rectangle_t rect = rectangle_from_area( area.min, area.max, self.Width(), self.Height() ); - self.m_XORRectangle.set( rect ); - - glDrawBuffer( GL_BACK ); - - GlobalOpenGL_debugAssertNoErrors(); - glwidget_make_current( self.GetWidget() ); + m_fbo->blit(); + return true; } } } + return false; +} +void XYWnd::XY_Draw_Overlay_finish(){ + glDrawBuffer( GL_BACK ); + GlobalOpenGL_debugAssertNoErrors(); + glwidget_make_current( m_gl_widget ); +} + +void xy_update_xor_rectangle( XYWnd& self, rect_t area ){ + if ( self.XY_Draw_Overlay_start() ) { + self.UpdateCameraIcon_(); + self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.Width(), self.Height() ), self.Width(), self.Height() ); + self.XY_Draw_Overlay_finish(); + } } gboolean xywnd_button_press( GtkWidget* widget, GdkEventButton* event, XYWnd* xywnd ){ @@ -873,9 +886,12 @@ XYWnd::XYWnd() : m_deferred_motion( xywnd_motion, this ), m_parent( 0 ), m_window_observer( NewWindowObserver() ), - m_chasemouse_handler( 0 ){ + m_chasemouse_handler( 0 ) +{ m_fbo = GlobalOpenGL().support_ARB_framebuffer_object? new FBO : new FBO_fallback; + m_cursorCurrent = 0; + m_bActive = false; m_buttonstate = 0; @@ -919,7 +935,7 @@ XYWnd::XYWnd() : g_signal_connect( G_OBJECT( m_gl_widget ), "button_press_event", G_CALLBACK( xywnd_button_press ), this ); g_signal_connect( G_OBJECT( m_gl_widget ), "button_release_event", G_CALLBACK( xywnd_button_release ), this ); - g_signal_connect( G_OBJECT( m_gl_widget ), "focus_in_event", G_CALLBACK( xywnd_focus_in ), this ); //works only in floating views layout + g_signal_connect( G_OBJECT( m_gl_widget ), "focus_in_event", G_CALLBACK( xywnd_focus_in ), this ); g_signal_connect( G_OBJECT( m_gl_widget ), "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &m_deferred_motion ); g_signal_connect( G_OBJECT( m_gl_widget ), "scroll_event", G_CALLBACK( xywnd_wheel_scroll ), this ); @@ -1055,34 +1071,26 @@ void XYWnd::Clipper_OnMouseMoved( int x, int y, bool snap ){ } } -//#include "gtkutil/image.h" +void XYWnd::CursorSet( GdkCursor* cursor ){ + if( m_cursorCurrent != cursor ){ + m_cursorCurrent = cursor; + gdk_window_set_cursor( m_gl_widget->window, m_cursorCurrent ); + } +} -/* is called on every mouse move fraction; ain't good! */ void XYWnd::Clipper_Crosshair_OnMouseMoved( int x, int y ){ - Vector3 mousePosition; - XY_ToPoint( x, y, mousePosition ); + GdkCursor* cursor = 0; if ( ClipMode() ) { + Vector3 mousePosition; + XY_ToPoint( x, y, mousePosition ); if( GlobalClipPoints_Find( mousePosition, m_viewType, m_fScale ) != 0 ){ - GdkCursor *cursor; - cursor = gdk_cursor_new( GDK_CROSSHAIR ); - //cursor = gdk_cursor_new( GDK_FLEUR ); - gdk_window_set_cursor( m_gl_widget->window, cursor ); - gdk_cursor_unref( cursor ); + cursor = g_cursorMoveClipper; } else{ - GdkCursor *cursor; - cursor = gdk_cursor_new( GDK_HAND2 ); -// GdkPixbuf* pixbuf = pixbuf_new_from_file_with_mask( "bitmaps/icon.png" ); -// cursor = gdk_cursor_new_from_pixbuf( gdk_display_get_default(), pixbuf, 0, 0 ); -// g_object_unref( pixbuf ); - gdk_window_set_cursor( m_gl_widget->window, cursor ); - gdk_cursor_unref( cursor ); + cursor = g_cursorClipper; } } - else - { - gdk_window_set_cursor( m_gl_widget->window, 0 ); - } + CursorSet( cursor ); } void XYWnd::SetCustomPivotOrigin( int pointx, int pointy ){ @@ -1634,7 +1642,9 @@ void XYWnd::XY_MouseMoved( int x, int y, unsigned int buttons ){ XYWnd_Update( *this ); } - Clipper_Crosshair_OnMouseMoved( x, y ); + if( ClipMode() ){ + Clipper_Crosshair_OnMouseMoved( x, y ); + } } } @@ -2345,43 +2355,37 @@ void XYWnd::DrawCameraIcon( const Vector3& origin, const Vector3& angles ){ } -void XYWnd::UpdateCameraIcon( void ){ - if ( glwidget_make_current( m_gl_widget ) != FALSE ) { - if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { - GlobalOpenGL_debugAssertNoErrors(); +void XYWnd::UpdateCameraIcon_(){ + glViewport( 0, 0, m_nWidth, m_nHeight ); - glDrawBuffer( GL_FRONT ); - m_fbo->blit(); + glMatrixMode( GL_PROJECTION ); + glLoadMatrixf( reinterpret_cast( &m_projection ) ); - glViewport( 0, 0, m_nWidth, m_nHeight ); - // set up viewpoint - glMatrixMode( GL_PROJECTION ); - glLoadMatrixf( reinterpret_cast( &m_projection ) ); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - glScalef( m_fScale, m_fScale, 1 ); - int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - int nDim2 = ( m_viewType == XY ) ? 1 : 2; - glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 ); + glScalef( m_fScale, m_fScale, 1 ); + int nDim1 = ( m_viewType == YZ ) ? 1 : 0; + int nDim2 = ( m_viewType == XY ) ? 1 : 2; + glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 ); - glDisable( GL_LINE_STIPPLE ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - glDisableClientState( GL_NORMAL_ARRAY ); - glDisableClientState( GL_COLOR_ARRAY ); - glDisable( GL_TEXTURE_2D ); - glDisable( GL_LIGHTING ); - glDisable( GL_COLOR_MATERIAL ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_TEXTURE_1D ); + glDisable( GL_LINE_STIPPLE ); + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState( GL_NORMAL_ARRAY ); + glDisableClientState( GL_COLOR_ARRAY ); + glDisable( GL_TEXTURE_2D ); + glDisable( GL_LIGHTING ); + glDisable( GL_COLOR_MATERIAL ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_TEXTURE_1D ); - XYWnd::DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) ); + DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) ); +} - glDrawBuffer( GL_BACK ); - - GlobalOpenGL_debugAssertNoErrors(); - glwidget_make_current( m_gl_widget ); - } +void XYWnd::UpdateCameraIcon(){ + if ( XY_Draw_Overlay_start() ) { + UpdateCameraIcon_(); + XY_Draw_Overlay_finish(); } } @@ -3452,11 +3456,23 @@ void XYWindow_Construct(){ Orthographic_registerPreferencesPage(); Clipper_registerPreferencesPage(); + g_cursorMoveClipper = gdk_cursor_new( GDK_CROSSHAIR ); + g_cursorClipper = gdk_cursor_new( GDK_HAND2 ); +// cursor = gdk_cursor_new( GDK_FLEUR ); +// gdk_cursor_unref( cursor ); +//#include "gtkutil/image.h" +// GdkPixbuf* pixbuf = pixbuf_new_from_file_with_mask( "bitmaps/icon.png" ); +// cursor = gdk_cursor_new_from_pixbuf( gdk_display_get_default(), pixbuf, 0, 0 ); +// g_object_unref( pixbuf ); + XYWnd::captureStates(); GlobalEntityClassManager().attach( g_EntityClassMenu ); } void XYWindow_Destroy(){ + gdk_cursor_unref( g_cursorMoveClipper ); + gdk_cursor_unref( g_cursorClipper ); + GlobalEntityClassManager().detach( g_EntityClassMenu ); XYWnd::releaseStates(); } diff --git a/radiant/xywindow.h b/radiant/xywindow.h index e0a1d4ee..eca14b2b 100644 --- a/radiant/xywindow.h +++ b/radiant/xywindow.h @@ -107,6 +107,8 @@ void SetOrigin( const Vector3& origin ); void Scroll( int x, int y ); void XY_Draw(); +bool XY_Draw_Overlay_start(); +void XY_Draw_Overlay_finish(); void DrawCameraIcon( const Vector3& origin, const Vector3& angles ); void XY_DrawBlockGrid(); void XY_DrawAxis(); @@ -150,6 +152,7 @@ bool Active(){ return m_bActive; }; void UpdateCameraIcon(); +void UpdateCameraIcon_(); void Clipper_OnLButtonDown( int x, int y ); @@ -215,8 +218,10 @@ int m_entityCreate_x, m_entityCreate_y; bool m_entityCreate; Timer m_render_time; +GdkCursor* m_cursorCurrent; public: +void CursorSet( GdkCursor* cursor ); void OnContextMenu(); void ButtonState_onMouseDown( unsigned int buttons ){ //m_buttonstate |= buttons;