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
This commit is contained in:
Garux 2017-08-02 09:53:07 +03:00
parent e14027e117
commit 6eee961fcc
18 changed files with 239 additions and 131 deletions

View File

@ -57,6 +57,9 @@ virtual bool fill() const = 0;
virtual const Matrix4& GetViewport() const = 0; virtual const Matrix4& GetViewport() const = 0;
virtual const Matrix4& GetProjection() const = 0; virtual const Matrix4& GetProjection() const = 0;
virtual const Matrix4& GetModelview() const = 0; virtual const Matrix4& GetModelview() const = 0;
virtual const Matrix4& GetViewMatrix() const = 0; //viewproj
virtual const Vector3& getViewer() const = 0;
}; };
class Cullable class Cullable

View File

@ -73,10 +73,19 @@ public:
} }
~XORRectangle() { ~XORRectangle() {
} }
void set( rectangle_t rectangle ) { void set( rectangle_t rectangle, int width, int height ) {
if( rectangle.w != 0.f && rectangle.h != 0.f ) { if( rectangle.w != 0.f && rectangle.h != 0.f ) {
GlobalOpenGL_debugAssertNoErrors(); 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 ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );

View File

@ -69,6 +69,8 @@ inline void PointVertexArray_testSelect( PointVertex* first, std::size_t count,
); );
} }
const char EXCLUDE_NAME[] = "worldspawn";
class Doom3Group : class Doom3Group :
public Bounded, public Bounded,
public Snappable public Snappable
@ -260,7 +262,7 @@ Doom3Group( EntityClass* eclass, scene::Node& node, const Callback& transformCha
m_nameKeys( m_entity ), m_nameKeys( m_entity ),
m_funcStaticOrigin( m_traverse, m_origin ), m_funcStaticOrigin( m_traverse, m_origin ),
m_name_origin( g_vector3_identity ), 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_skin( SkinChangedCaller( *this ) ),
m_curveNURBS( boundsChanged ), m_curveNURBS( boundsChanged ),
m_curveCatmullRom( boundsChanged ), m_curveCatmullRom( boundsChanged ),
@ -279,7 +281,7 @@ Doom3Group( const Doom3Group& other, scene::Node& node, const Callback& transfor
m_nameKeys( m_entity ), m_nameKeys( m_entity ),
m_funcStaticOrigin( m_traverse, m_origin ), m_funcStaticOrigin( m_traverse, m_origin ),
m_name_origin( g_vector3_identity ), 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_skin( SkinChangedCaller( *this ) ),
m_curveNURBS( boundsChanged ), m_curveNURBS( boundsChanged ),
m_curveCatmullRom( 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 ); 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 // draw models as usual
if ( !isModel() ) { if ( !isModel() ) {
// don't draw the name for worldspawn // don't draw the name for worldspawn
if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { // if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) {
return; // return;
} // }
// place name in the middle of the "children cloud" // place name in the middle of the "children cloud"
m_name_origin = childBounds.origin; m_name_origin = childBounds.origin;

View File

@ -49,6 +49,8 @@
/// The "origin" key directly controls the entity's local-to-parent transform. /// The "origin" key directly controls the entity's local-to-parent transform.
const char EXCLUDE_NAME[] = "worldspawn";
class Group class Group
{ {
EntityKeyValues m_entity; EntityKeyValues m_entity;
@ -84,7 +86,7 @@ Group( EntityClass* eclass, scene::Node& node, const Callback& transformChanged,
m_originKey( OriginChangedCaller( *this ) ), m_originKey( OriginChangedCaller( *this ) ),
m_origin( ORIGINKEY_IDENTITY ), m_origin( ORIGINKEY_IDENTITY ),
m_name_origin( g_vector3_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_transformChanged( transformChanged ),
m_evaluateTransform( evaluateTransform ){ m_evaluateTransform( evaluateTransform ){
construct(); construct();
@ -97,7 +99,7 @@ Group( const Group& other, scene::Node& node, const Callback& transformChanged,
m_originKey( OriginChangedCaller( *this ) ), m_originKey( OriginChangedCaller( *this ) ),
m_origin( ORIGINKEY_IDENTITY ), m_origin( ORIGINKEY_IDENTITY ),
m_name_origin( g_vector3_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_transformChanged( transformChanged ),
m_evaluateTransform( evaluateTransform ){ m_evaluateTransform( evaluateTransform ){
construct(); 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 { 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 ); 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 // don't draw the name for worldspawn
if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { // if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) {
return; // return;
} // }
// place name in the middle of the "children cloud" // place name in the middle of the "children cloud"
m_name_origin = childBounds.origin; m_name_origin = childBounds.origin;

View File

@ -1066,6 +1066,8 @@ inline Matrix4 matrix4_from_planes( const Plane3& left, const Plane3& right, con
); );
} }
const char EXCLUDE_NAME[] = "light";
class Light : class Light :
public OpenGLRenderable, public OpenGLRenderable,
public Cullable, 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_fill( m_radii, m_aabb_light.origin ),
m_radii_box( m_aabb_light.origin ), m_radii_box( m_aabb_light.origin ),
m_render_center( m_doom3Radius.m_center, m_entity.getEntityClass() ), 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_useLightOrigin( false ),
m_useLightRotation( false ), m_useLightRotation( false ),
m_renderProjection( m_doom3Projection ), 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_fill( m_radii, m_aabb_light.origin ),
m_radii_box( m_aabb_light.origin ), m_radii_box( m_aabb_light.origin ),
m_render_center( m_doom3Radius.m_center, m_entity.getEntityClass() ), 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_useLightOrigin( false ),
m_useLightRotation( false ), m_useLightRotation( false ),
m_renderProjection( m_doom3Projection ), 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 ); m_renderName.render( renderer, volume, localToWorld, selected );
} }
} }

View File

@ -50,6 +50,8 @@
#include "entity.h" #include "entity.h"
const char EXCLUDE_NAME[] = "misc_model";
class MiscModel : class MiscModel :
public Snappable public Snappable
{ {
@ -125,7 +127,7 @@ MiscModel( EntityClass* eclass, scene::Node& node, const Callback& transformChan
m_filter( m_entity, node ), m_filter( m_entity, node ),
m_named( m_entity ), m_named( m_entity ),
m_nameKeys( 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_transformChanged( transformChanged ),
m_evaluateTransform( evaluateTransform ){ m_evaluateTransform( evaluateTransform ){
construct(); construct();
@ -141,7 +143,7 @@ MiscModel( const MiscModel& other, scene::Node& node, const Callback& transformC
m_filter( m_entity, node ), m_filter( m_entity, node ),
m_named( m_entity ), m_named( m_entity ),
m_nameKeys( 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_transformChanged( transformChanged ),
m_evaluateTransform( evaluateTransform ){ m_evaluateTransform( evaluateTransform ){
construct(); construct();
@ -195,7 +197,8 @@ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& l
m_renderOrigin.render( renderer, volume, localToWorld ); m_renderOrigin.render( renderer, volume, localToWorld );
} }
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); 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 ); m_renderName.render( renderer, volume, localToWorld, selected );
} }
} }

View File

@ -91,8 +91,9 @@ typedef MemberCaller1<NamedEntity, const char*, &NamedEntity::identifierChanged>
#include "renderable.h" #include "renderable.h"
#include "pivot.h" //#include "pivot.h"
#include "math/frustum.h" //#include "math/frustum.h"
#include "cullable.h"
class RenderableNamedEntity : public OpenGLRenderable { class RenderableNamedEntity : public OpenGLRenderable {
enum ENameMode{ enum ENameMode{
@ -108,18 +109,24 @@ class RenderableNamedEntity : public OpenGLRenderable {
int m_width; int m_width;
int m_height; int m_height;
mutable float m_screenPos[2]; mutable float m_screenPos[2];
const char* m_exclude;
public: public:
typedef Static<Shader*, RenderableNamedEntity> StaticShader; typedef Static<Shader*, RenderableNamedEntity> StaticShader;
static Shader* getShader() { static Shader* getShader() {
return StaticShader::instance(); return StaticShader::instance();
} }
RenderableNamedEntity( NamedEntity& named, const Vector3& position ) RenderableNamedEntity( NamedEntity& named, const Vector3& position, const char* exclude = 0 )
: m_named( named ), m_position( position ), m_tex( 0 ) { : m_named( named ), m_position( position ), m_tex( 0 ), m_exclude( exclude ) {
construct_textures( g_showTargetNames ? m_named.name() : m_named.classname() ); construct_textures( g_showTargetNames ? m_named.name() : m_named.classname() );
m_named.attach( IdentifierChangedCaller( *this ) ); m_named.attach( IdentifierChangedCaller( *this ) );
} }
bool excluded_not() const {
return m_tex > 0;
}
private: private:
void construct_textures( const char* name ){ void construct_textures( const char* name ){
if( m_exclude && string_equal( m_exclude, name ) )
return;
glGenTextures( 1, &m_tex ); glGenTextures( 1, &m_tex );
if( m_tex > 0 ) { if( m_tex > 0 ) {
unsigned int colour[3]; 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{ void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected = false ) const{
setMode( selected, childSelected ); setMode( selected, childSelected );
if( m_nameMode == eNameNormal && volume.fill() ){ if( volume.fill() ){
// globalOutputStream() << localToWorld << " localToWorld\n"; // globalOutputStream() << localToWorld << " localToWorld\n";
// globalOutputStream() << volume.GetModelview() << " modelview\n"; // globalOutputStream() << volume.GetModelview() << " modelview\n";
// globalOutputStream() << volume.GetProjection() << " Projection\n"; // globalOutputStream() << volume.GetProjection() << " Projection\n";
// globalOutputStream() << volume.GetViewport() << " Viewport\n"; // globalOutputStream() << volume.GetViewport() << " Viewport\n";
Matrix4 viewproj = matrix4_multiplied_by_matrix4( volume.GetProjection(), volume.GetModelview() ); //Matrix4 viewproj = matrix4_multiplied_by_matrix4( volume.GetProjection(), volume.GetModelview() );
Vector3 viewer = vector4_to_vector3( viewer_from_viewproj( viewproj ) ); const Matrix4& viewproj = volume.GetViewMatrix();
Vector3 pos_in_world = matrix4_transformed_point( localToWorld, m_position ); //Vector3 viewer = vector4_to_vector3( viewer_from_viewproj( viewproj ) );
if( vector3_length_squared( pos_in_world - viewer ) > g_showNamesDist * g_showNamesDist ){ 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; return;
} if( m_nameMode == eNameNormal && vector3_length_squared( pos_in_world - volume.getViewer() ) > static_cast<float>( g_showNamesDist ) * static_cast<float>( g_showNamesDist ) )
return;
//globalOutputStream() << viewer[0] << " " << viewer[1] << " " << viewer[2] << " Viewer\n"; //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] << " m_position\n";
//globalOutputStream() << m_position[0] << " " << m_position[1] << " " << m_position[2] << " position\n"; //globalOutputStream() << pos_in_world[0] << " " << pos_in_world[1] << " " << pos_in_world[2] << " pos_in_world\n";
} }
Vector4 position; Vector4 position( m_position, 1.f );
position[0] = m_position[0];
position[1] = m_position[1];
position[2] = m_position[2];
position[3] = 1.f;
#if 0 #if 0
// globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " position\n"; // 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"; // globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " Viewport\n";
#else #else
Matrix4 object2screen = volume.GetProjection(); //Matrix4 object2screen = volume.GetProjection();
matrix4_multiply_by_matrix4( object2screen, volume.GetModelview() ); Matrix4 object2screen( volume.GetViewMatrix() );
//matrix4_multiply_by_matrix4( object2screen, volume.GetModelview() );
matrix4_multiply_by_matrix4( object2screen, localToWorld ); matrix4_multiply_by_matrix4( object2screen, localToWorld );
// globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " position\n"; // globalOutputStream() << position[0] << " " << position[1] << " " << position[2] << " " << position[3] << " position\n";
matrix4_transform_vector4( object2screen, position ); matrix4_transform_vector4( object2screen, position );

View File

@ -757,6 +757,28 @@ void Scene_BrushProjectTexture_Component_Selected( scene::Graph& graph, const te
SceneChangeNotify(); 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 class FaceFitTexture
{ {

View File

@ -80,6 +80,8 @@ template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3; typedef BasicVector3<float> Vector3;
void Scene_BrushProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ); 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_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_Selected( scene::Graph& graph, float s_repeat, float t_repeat );
void Scene_BrushFitTexture_Component_Selected( scene::Graph& graph, float s_repeat, float t_repeat ); void Scene_BrushFitTexture_Component_Selected( scene::Graph& graph, float s_repeat, float t_repeat );

View File

@ -950,16 +950,7 @@ void camwnd_update_xor_rectangle( CamWnd& self, rect_t area ){
glDrawBuffer( GL_FRONT ); glDrawBuffer( GL_FRONT );
self.m_fbo->blit(); self.m_fbo->blit();
glViewport( 0, 0, 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 );
// 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 ) );
glDrawBuffer( GL_BACK ); glDrawBuffer( GL_BACK );

View File

@ -319,6 +319,23 @@ void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& te
SceneChangeNotify(); 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 class PatchFlipTexture
{ {
int m_axis; int m_axis;

View File

@ -46,6 +46,8 @@ class texdef_t;
template<typename Element> class BasicVector3; template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3; typedef BasicVector3<float> Vector3;
void Scene_PatchProjectTexture_Selected( scene::Graph& graph, const texdef_t& texdef, const Vector3* direction ); 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_PatchNaturalTexture_Selected( scene::Graph& graph );
void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t ); void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t );

View File

@ -898,6 +898,16 @@ void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ){
SceneChangeNotify(); 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 ){ void Select_FitTexture( float horizontal, float vertical ){
if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) {
Scene_BrushFitTexture_Selected( GlobalSceneGraph(), horizontal, vertical ); Scene_BrushFitTexture_Selected( GlobalSceneGraph(), horizontal, vertical );

View File

@ -69,6 +69,7 @@ void Select_ScaleTexture( float x, float y );
void Select_ShiftTexture( float x, float y ); void Select_ShiftTexture( float x, float y );
class texdef_t; class texdef_t;
void Select_ProjectTexture( const texdef_t& texdef, const Vector3* direction ); 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 Select_FitTexture( float horizontal = 1, float vertical = 1 );
void FindReplaceTextures( const char* pFind, const char* pReplace, bool bSelected ); void FindReplaceTextures( const char* pFind, const char* pReplace, bool bSelected );

View File

@ -4100,7 +4100,7 @@ const ModifierFlags c_modifier_copy_texture = c_modifierNone;
void Scene_copyClosestTexture( SelectionTest& test ); 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 ); void Scene_projectClosestTexture( SelectionTest& test );
class TexManipulator_ 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 ) { 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; m_undo_begun = true;
GlobalUndoSystem().start(); 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 ) { else if ( m_state == c_modifier_copy_texture ) {
Scene_copyClosestTexture( volume ); Scene_copyClosestTexture( volume );
@ -4142,7 +4142,7 @@ typedef MemberCaller1<TexManipulator_, DeviceVector, &TexManipulator_::mouseMove
void mouseUp( DeviceVector position ){ void mouseUp( DeviceVector position ){
if( m_undo_begun ){ if( m_undo_begun ){
GlobalUndoSystem().finish( ( m_state == c_modifier_apply_texture1_project ) ? "projectTexture" : "paintTexture" ); GlobalUndoSystem().finish( ( m_state == c_modifier_apply_texture1_project )? "projectTexture" : ( m_state == c_modifier_apply_texture2_seamless )? "paintTextureSeamless" : "paintTexture&Projection" );
m_undo_begun = false; m_undo_begun = false;
} }
g_mouseMovedCallback.clear(); g_mouseMovedCallback.clear();

View File

@ -1718,15 +1718,26 @@ void Scene_copyClosestTexture( SelectionTest& test ){
CopiedString shader; CopiedString shader;
if ( Scene_getClosestTexture( GlobalSceneGraph(), test, shader, g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ) ) { if ( Scene_getClosestTexture( GlobalSceneGraph(), test, shader, g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ) ) {
TextureBrowser_SetSelectedShader( g_TextureBrowser, shader.c_str() ); TextureBrowser_SetSelectedShader( g_TextureBrowser, shader.c_str() );
UndoableCommand undo( "textureNameAndProjectionSetSelected" ); // UndoableCommand undo( "textureNameAndProjectionSetSelected" );
Select_SetShader( shader.c_str() ); // Select_SetShader( shader.c_str() );
Select_SetTexdef( g_faceTextureClipboard.m_projection ); // Select_SetTexdef( g_faceTextureClipboard.m_projection );
} }
} }
void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project ){ void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project, bool texturize_selected = false ){
// UndoableCommand command( "facePaintTexture" ); // UndoableCommand command( "facePaintTexture" );
if( texturize_selected ){
if( project ){
Select_SetShader( TextureBrowser_GetSelectedShader( g_TextureBrowser ) );
Select_ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() );
}
else if( !seamless ){
Select_SetShader( TextureBrowser_GetSelectedShader( g_TextureBrowser ) );
Select_SetTexdef( g_faceTextureClipboard.m_projection );
}
}
Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless, project ); Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless, project );
SceneChangeNotify(); SceneChangeNotify();

View File

@ -121,6 +121,9 @@ ClipPoint g_Clip2;
ClipPoint g_Clip3; ClipPoint g_Clip3;
ClipPoint* g_pMovingClip = 0; ClipPoint* g_pMovingClip = 0;
GdkCursor* g_cursorClipper;
GdkCursor* g_cursorMoveClipper;
/* Drawing clip points */ /* Drawing clip points */
void ClipPoint::Draw( int num, float scale ){ void ClipPoint::Draw( int num, float scale ){
StringOutputStream label( 4 ); StringOutputStream label( 4 );
@ -302,6 +305,19 @@ void OnClipMode( bool enabled ){
g_pMovingClip = 0; g_pMovingClip = 0;
} }
if( g_pParentWnd ){
GdkCursor* cursor = enabled? g_cursorClipper : 0;
if( g_pParentWnd->GetXYWnd() ){
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(); Clip_Update();
} }
@ -746,33 +762,30 @@ bool XYWnd::chaseMouseMotion( int pointx, int pointy ){
// XYWnd class // XYWnd class
Shader* XYWnd::m_state_selected = 0; Shader* XYWnd::m_state_selected = 0;
void xy_update_xor_rectangle( XYWnd& self, rect_t area ){ bool XYWnd::XY_Draw_Overlay_start(){
if ( GTK_WIDGET_VISIBLE( self.GetWidget() ) ) { if ( GTK_WIDGET_VISIBLE( m_gl_widget ) ) {
if ( glwidget_make_current( self.GetWidget() ) != FALSE ) { if ( glwidget_make_current( m_gl_widget ) != FALSE ) {
if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
GlobalOpenGL_debugAssertNoErrors(); GlobalOpenGL_debugAssertNoErrors();
glDrawBuffer( GL_FRONT ); glDrawBuffer( GL_FRONT );
self.m_fbo->blit(); m_fbo->blit();
return true;
glViewport( 0, 0, self.Width(), self.Height() ); }
// set up viewpoint }
glMatrixMode( GL_PROJECTION ); }
glLoadIdentity(); return false;
glOrtho( 0, self.Width(), 0, self.Height(), -100, 100 ); }
void XYWnd::XY_Draw_Overlay_finish(){
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 ); glDrawBuffer( GL_BACK );
GlobalOpenGL_debugAssertNoErrors(); GlobalOpenGL_debugAssertNoErrors();
glwidget_make_current( self.GetWidget() ); 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();
} }
} }
@ -873,9 +886,12 @@ XYWnd::XYWnd() :
m_deferred_motion( xywnd_motion, this ), m_deferred_motion( xywnd_motion, this ),
m_parent( 0 ), m_parent( 0 ),
m_window_observer( NewWindowObserver() ), 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_fbo = GlobalOpenGL().support_ARB_framebuffer_object? new FBO : new FBO_fallback;
m_cursorCurrent = 0;
m_bActive = false; m_bActive = false;
m_buttonstate = 0; 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_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 ), "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 ), "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 ); 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 ){ void XYWnd::Clipper_Crosshair_OnMouseMoved( int x, int y ){
GdkCursor* cursor = 0;
if ( ClipMode() ) {
Vector3 mousePosition; Vector3 mousePosition;
XY_ToPoint( x, y, mousePosition ); XY_ToPoint( x, y, mousePosition );
if ( ClipMode() ) {
if( GlobalClipPoints_Find( mousePosition, m_viewType, m_fScale ) != 0 ){ if( GlobalClipPoints_Find( mousePosition, m_viewType, m_fScale ) != 0 ){
GdkCursor *cursor; cursor = g_cursorMoveClipper;
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 );
} }
else{ else{
GdkCursor *cursor; cursor = g_cursorClipper;
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 );
} }
} }
else CursorSet( cursor );
{
gdk_window_set_cursor( m_gl_widget->window, 0 );
}
} }
void XYWnd::SetCustomPivotOrigin( int pointx, int pointy ){ void XYWnd::SetCustomPivotOrigin( int pointx, int pointy ){
@ -1634,8 +1642,10 @@ void XYWnd::XY_MouseMoved( int x, int y, unsigned int buttons ){
XYWnd_Update( *this ); XYWnd_Update( *this );
} }
if( ClipMode() ){
Clipper_Crosshair_OnMouseMoved( x, y ); Clipper_Crosshair_OnMouseMoved( x, y );
} }
}
} }
void XYWnd::EntityCreate_MouseDown( int x, int y ){ void XYWnd::EntityCreate_MouseDown( int x, int y ){
@ -2345,21 +2355,15 @@ void XYWnd::DrawCameraIcon( const Vector3& origin, const Vector3& angles ){
} }
void XYWnd::UpdateCameraIcon( void ){ void XYWnd::UpdateCameraIcon_(){
if ( glwidget_make_current( m_gl_widget ) != FALSE ) {
if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
GlobalOpenGL_debugAssertNoErrors();
glDrawBuffer( GL_FRONT );
m_fbo->blit();
glViewport( 0, 0, m_nWidth, m_nHeight ); glViewport( 0, 0, m_nWidth, m_nHeight );
// set up viewpoint
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glLoadMatrixf( reinterpret_cast<const float*>( &m_projection ) ); glLoadMatrixf( reinterpret_cast<const float*>( &m_projection ) );
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); glLoadIdentity();
glScalef( m_fScale, m_fScale, 1 ); glScalef( m_fScale, m_fScale, 1 );
int nDim1 = ( m_viewType == YZ ) ? 1 : 0; int nDim1 = ( m_viewType == YZ ) ? 1 : 0;
int nDim2 = ( m_viewType == XY ) ? 1 : 2; int nDim2 = ( m_viewType == XY ) ? 1 : 2;
@ -2375,13 +2379,13 @@ void XYWnd::UpdateCameraIcon( void ){
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_1D ); 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 ); void XYWnd::UpdateCameraIcon(){
if ( XY_Draw_Overlay_start() ) {
GlobalOpenGL_debugAssertNoErrors(); UpdateCameraIcon_();
glwidget_make_current( m_gl_widget ); XY_Draw_Overlay_finish();
}
} }
} }
@ -3452,11 +3456,23 @@ void XYWindow_Construct(){
Orthographic_registerPreferencesPage(); Orthographic_registerPreferencesPage();
Clipper_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(); XYWnd::captureStates();
GlobalEntityClassManager().attach( g_EntityClassMenu ); GlobalEntityClassManager().attach( g_EntityClassMenu );
} }
void XYWindow_Destroy(){ void XYWindow_Destroy(){
gdk_cursor_unref( g_cursorMoveClipper );
gdk_cursor_unref( g_cursorClipper );
GlobalEntityClassManager().detach( g_EntityClassMenu ); GlobalEntityClassManager().detach( g_EntityClassMenu );
XYWnd::releaseStates(); XYWnd::releaseStates();
} }

View File

@ -107,6 +107,8 @@ void SetOrigin( const Vector3& origin );
void Scroll( int x, int y ); void Scroll( int x, int y );
void XY_Draw(); void XY_Draw();
bool XY_Draw_Overlay_start();
void XY_Draw_Overlay_finish();
void DrawCameraIcon( const Vector3& origin, const Vector3& angles ); void DrawCameraIcon( const Vector3& origin, const Vector3& angles );
void XY_DrawBlockGrid(); void XY_DrawBlockGrid();
void XY_DrawAxis(); void XY_DrawAxis();
@ -150,6 +152,7 @@ bool Active(){
return m_bActive; return m_bActive;
}; };
void UpdateCameraIcon(); void UpdateCameraIcon();
void UpdateCameraIcon_();
void Clipper_OnLButtonDown( int x, int y ); void Clipper_OnLButtonDown( int x, int y );
@ -215,8 +218,10 @@ int m_entityCreate_x, m_entityCreate_y;
bool m_entityCreate; bool m_entityCreate;
Timer m_render_time; Timer m_render_time;
GdkCursor* m_cursorCurrent;
public: public:
void CursorSet( GdkCursor* cursor );
void OnContextMenu(); void OnContextMenu();
void ButtonState_onMouseDown( unsigned int buttons ){ void ButtonState_onMouseDown( unsigned int buttons ){
//m_buttonstate |= buttons; //m_buttonstate |= buttons;