diff --git a/libs/gtkutil/glfont.cpp b/libs/gtkutil/glfont.cpp index cc11bd37..6d0f0b2b 100644 --- a/libs/gtkutil/glfont.cpp +++ b/libs/gtkutil/glfont.cpp @@ -25,6 +25,70 @@ #include #include + +void gray_to_texture( const int x_max, const int y_max, const unsigned char *in, unsigned char *out, const unsigned int fontColorR, const unsigned int fontColorG, const unsigned int fontColorB ){ /* normal with shadow */ + int x, y, bitmapIter = 0; + + const unsigned int backgroundColorR = 0; + const unsigned int backgroundColorG = 0; + const unsigned int backgroundColorB = 0; + + for( y = 0; y < y_max; y++ ) { + for( x = 0; x < x_max; x++ ) { + int iter = ( y * x_max + x ) * 4; + if( x == 0 || y == 0 || x == 1 || y == 1 ) { + out[iter] = fontColorB; + out[iter + 1] = fontColorG; + out[iter + 2] = fontColorR; + out[iter + 3] = 0; + continue; + } + if( in[bitmapIter] == 0 ){ + out[iter] = fontColorB; + out[iter + 1] = fontColorG; + out[iter + 2] = fontColorR; + out[iter + 3] = 0; + } + else{ + out[iter] = backgroundColorB; + out[iter + 1] = backgroundColorG; + out[iter + 2] = backgroundColorR; + out[iter + 3] = in[bitmapIter]; + } + ++bitmapIter; + } + } + + bitmapIter = 0; + for( y = 0; y < y_max; y++ ) { + for( x = 0; x < x_max; x++ ) { + int iter = ( y * x_max + x ) * 4; + if( x == 0 || y == 0 || x == ( x_max - 1 ) || y == ( y_max - 1 ) ) { + continue; + } + if( in[bitmapIter] != 0 ) { + if( out[iter + 3] == 0 ){ + out[iter] = fontColorB; + out[iter + 1] = fontColorG; + out[iter + 2] = fontColorR; + out[iter + 3] = in[bitmapIter]; + } + else{ + /* Calculate alpha (opacity). */ + float opacityFont = in[bitmapIter] / 255.f; + float opacityBack = out[iter + 3] / 255.f; + out[iter] = fontColorB * opacityFont + ( 1 - opacityFont ) * backgroundColorB; + out[iter + 1] = fontColorG * opacityFont + ( 1 - opacityFont ) * backgroundColorG; + out[iter + 2] = fontColorR * opacityFont + ( 1 - opacityFont ) * backgroundColorR; + out[iter + 3] = ( opacityFont + ( 1 - opacityFont ) * opacityBack ) * 255.f; + } + } + ++bitmapIter; + } + } +} + + // generic string printing with call lists class GLFontCallList : public GLFont { @@ -153,7 +217,7 @@ void renderString( const char *s, const GLuint& tex, const unsigned int colour[3 } } } -#else +#elif 0 if( 1 ){ /* normal with shadow */ int x_max = wid; int y_max = hei; @@ -224,7 +288,6 @@ void renderString( const char *s, const GLuint& tex, const unsigned int colour[3 } } } -#endif // 0 else{ /* normal */ int x_max = wid; int y_max = hei; @@ -255,6 +318,7 @@ void renderString( const char *s, const GLuint& tex, const unsigned int colour[3 } } } +#endif // 0 @@ -273,8 +337,23 @@ void renderString( const char *s, const GLuint& tex, const unsigned int colour[3 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); //Here we actually create the texture itself - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, wid, hei, - 0, GL_BGRA, GL_UNSIGNED_BYTE, buf ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, wid * 3, hei, + 0, GL_BGRA, GL_UNSIGNED_BYTE, 0 ); + + /* normal with shadow */ + gray_to_texture( wid, hei, bitmap.buffer, buf, colour[0], colour[1], colour[2] ); + glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, wid, hei, GL_BGRA, GL_UNSIGNED_BYTE, buf ); + + memset( buf, 0x00, 4 * hei * wid ); + /* yellow selected with shadow */ + gray_to_texture( wid, hei, bitmap.buffer, buf, 255, 255, 0 ); + glTexSubImage2D( GL_TEXTURE_2D, 0, wid, 0, wid, hei, GL_BGRA, GL_UNSIGNED_BYTE, buf ); + + memset( buf, 0x00, 4 * hei * wid ); + /* orange childSselected with shadow */ + gray_to_texture( wid, hei, bitmap.buffer, buf, 255, 128, 0 ); + glTexSubImage2D( GL_TEXTURE_2D, 0, wid * 2, 0, wid, hei, GL_BGRA, GL_UNSIGNED_BYTE, buf ); + glBindTexture( GL_TEXTURE_2D, 0 ); diff --git a/plugins/entity/doom3group.cpp b/plugins/entity/doom3group.cpp index 54ecefb1..7e950f30 100644 --- a/plugins/entity/doom3group.cpp +++ b/plugins/entity/doom3group.cpp @@ -348,7 +348,7 @@ const AABB& localAABB() const { return m_curveBounds; } -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, const AABB& childBounds ) const { +void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected, const AABB& childBounds ) const { if ( isModel() && selected ) { m_renderOrigin.render( renderer, volume, localToWorld ); } @@ -375,12 +375,12 @@ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& l m_name_origin = childBounds.origin; } - m_renderName.render( renderer, volume, localToWorld, selected ); + m_renderName.render( renderer, volume, localToWorld, selected, childSelected ); } } -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, const AABB& childBounds ) const { - renderSolid( renderer, volume, localToWorld, selected, childBounds ); +void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected, const AABB& childBounds ) const { + renderSolid( renderer, volume, localToWorld, selected, childSelected, childBounds ); } void testSelect( Selector& selector, SelectionTest& test, SelectionIntersection& best ){ @@ -499,13 +499,13 @@ Doom3GroupInstance( const scene::Path& path, scene::Instance* parent, Doom3Group m_contained.instanceDetach( Instance::path() ); } void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childBounds() ); + m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childSelected(), Instance::childBounds() ); m_curveNURBS.renderComponentsSelected( renderer, volume, localToWorld() ); m_curveCatmullRom.renderComponentsSelected( renderer, volume, localToWorld() ); } void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childBounds() ); + m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childSelected(), Instance::childBounds() ); m_curveNURBS.renderComponentsSelected( renderer, volume, localToWorld() ); m_curveCatmullRom.renderComponentsSelected( renderer, volume, localToWorld() ); diff --git a/plugins/entity/group.cpp b/plugins/entity/group.cpp index 861f57fa..24148f2d 100644 --- a/plugins/entity/group.cpp +++ b/plugins/entity/group.cpp @@ -148,7 +148,7 @@ void detach( scene::Traversable::Observer* observer ){ m_traverse.detach( observer ); } -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, 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 ); if ( g_showNames ) { // don't draw the name for worldspawn @@ -159,12 +159,12 @@ void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& l // place name in the middle of the "children cloud" m_name_origin = childBounds.origin; - m_renderName.render( renderer, volume, localToWorld, selected ); + m_renderName.render( renderer, volume, localToWorld, selected, childSelected ); } } -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, const AABB& childBounds ) const { - renderSolid( renderer, volume, localToWorld, selected, childBounds ); +void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected, const AABB& childBounds ) const { + renderSolid( renderer, volume, localToWorld, selected, childSelected, childBounds ); } void updateTransform(){ @@ -298,10 +298,10 @@ GroupInstance( const scene::Path& path, scene::Instance* parent, Group& group ) m_contained.instanceDetach( Instance::path() ); } void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childBounds() ); + m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childSelected(), Instance::childBounds() ); } void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childBounds() ); + m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childSelected(), Instance::childBounds() ); } STRING_CONSTANT( Name, "GroupInstance" ); diff --git a/plugins/entity/namedentity.h b/plugins/entity/namedentity.h index 80e68f82..9fdd46c0 100644 --- a/plugins/entity/namedentity.h +++ b/plugins/entity/namedentity.h @@ -95,14 +95,18 @@ typedef MemberCaller1 #include "math/frustum.h" class RenderableNamedEntity : public OpenGLRenderable { + enum ENameMode{ + eNameNormal = 0, + eNameSelected = 1, + eNameChildSelected = 2, + }; + mutable ENameMode m_nameMode; + NamedEntity& m_named; const Vector3& m_position; - mutable GLuint m_tex_normal; - mutable GLuint m_tex_selected; - mutable GLuint* m_tex; + GLuint m_tex; int m_width; int m_height; - unsigned int m_colour[3]; mutable float m_screenPos[2]; public: typedef Static StaticShader; @@ -110,50 +114,40 @@ public: return StaticShader::instance(); } RenderableNamedEntity( NamedEntity& named, const Vector3& position ) - : m_named( named ), m_position( position ), m_tex_normal( 0 ), m_tex_selected( 0 ) { + : m_named( named ), m_position( position ), m_tex( 0 ) { construct_textures( g_showTargetNames ? m_named.name() : m_named.classname() ); m_named.attach( IdentifierChangedCaller( *this ) ); } private: - void setSelected( bool selected ) const { - m_tex = selected ? &m_tex_selected : &m_tex_normal; - } - void setSelectedColour( bool selected ){ - if( selected ){ - m_colour[0] = 255; - m_colour[1] = 255; - m_colour[2] = 0; - } - else{ - m_colour[0] = static_cast( m_named.color()[0] * 255.f ); - m_colour[1] = static_cast( m_named.color()[1] * 255.f ); - m_colour[2] = static_cast( m_named.color()[2] * 255.f ); - } - } - void construct_texture( const char* name ){ - glGenTextures( 1, m_tex ); - if( *m_tex > 0 ) { - GlobalOpenGL().m_font->renderString( name, *m_tex, m_colour, m_width, m_height ); - } - } void construct_textures( const char* name ){ - setSelected( false ); - setSelectedColour( false ); - construct_texture( name ); - setSelected( true ); - setSelectedColour( true ); - construct_texture( name ); + glGenTextures( 1, &m_tex ); + if( m_tex > 0 ) { + unsigned int colour[3]; + colour[0] = static_cast( m_named.color()[0] * 255.f ); + colour[1] = static_cast( m_named.color()[1] * 255.f ); + colour[2] = static_cast( m_named.color()[2] * 255.f ); + GlobalOpenGL().m_font->renderString( name, m_tex, colour, m_width, m_height ); + } } void delete_textures(){ - glDeleteTextures( 1, &m_tex_normal ); - glDeleteTextures( 1, &m_tex_selected ); - m_tex_normal = 0; - m_tex_selected = 0; + glDeleteTextures( 1, &m_tex ); + m_tex = 0; + } + void setMode( bool selected, bool childSelected ) const{ + if( selected ){ + m_nameMode = eNameSelected; + } + else if( childSelected ){ + m_nameMode = eNameChildSelected; + } + else{ + m_nameMode = eNameNormal; + } } public: void render( RenderStateFlags state ) const { - if( *m_tex > 0 ){ - glBindTexture( GL_TEXTURE_2D, *m_tex ); + if( m_tex > 0 ){ + glBindTexture( GL_TEXTURE_2D, m_tex ); //Here we draw the texturemaped quads. //The bitmap that we got from FreeType was not @@ -161,21 +155,25 @@ public: //so we need to link the texture to the quad //so that the result will be properly aligned. glBegin( GL_QUADS ); - glTexCoord2i( 0, 1 ); + float xoffset0 = m_nameMode / 3.f; + float xoffset1 = ( m_nameMode + 1 ) / 3.f; + glTexCoord2f( xoffset0, 1 ); glVertex2f( m_screenPos[0], m_screenPos[1] ); - glTexCoord2i( 0, 0 ); + glTexCoord2f( xoffset0, 0 ); glVertex2f( m_screenPos[0], m_screenPos[1] + m_height + .01f ); - glTexCoord2i( 1, 0 ); + glTexCoord2f( xoffset1, 0 ); glVertex2f( m_screenPos[0] + m_width + .01f, m_screenPos[1] + m_height + .01f ); - glTexCoord2i( 1, 1 ); + glTexCoord2f( xoffset1, 1 ); glVertex2f( m_screenPos[0] + m_width + .01f, m_screenPos[1] ); glEnd(); glBindTexture( GL_TEXTURE_2D, 0 ); } } - void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const{ - if( !selected && volume.fill() ){ + 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() ){ // globalOutputStream() << localToWorld << " localToWorld\n"; // globalOutputStream() << volume.GetModelview() << " modelview\n"; // globalOutputStream() << volume.GetProjection() << " Projection\n"; @@ -191,7 +189,6 @@ public: //globalOutputStream() << m_position[0] << " " << m_position[1] << " " << m_position[2] << " position\n"; } - setSelected( selected ); Vector4 position; position[0] = m_position[0];