diff --git a/libs/gtkutil/xorrectangle.h b/libs/gtkutil/xorrectangle.h index fc1965df..9c7791a5 100644 --- a/libs/gtkutil/xorrectangle.h +++ b/libs/gtkutil/xorrectangle.h @@ -22,66 +22,32 @@ #if !defined ( INCLUDED_XORRECTANGLE_H ) #define INCLUDED_XORRECTANGLE_H -#include -#include "math/vector.h" - - -#include "gtkutil/glwidget.h" +#include "rect_t.h" #include "igl.h" -#include - -//#include "stream/stringstream.h" - - -class rectangle_t -{ -public: -rectangle_t() - : x( 0 ), y( 0 ), w( 0 ), h( 0 ) -{} -rectangle_t( float _x, float _y, float _w, float _h ) - : x( _x ), y( _y ), w( _w ), h( _h ) -{} -float x; -float y; -float w; -float h; -}; - -struct Coord2D -{ - float x, y; - Coord2D( float _x, float _y ) - : x( _x ), y( _y ){ - } -}; - -inline Coord2D coord2d_device2screen( const Coord2D& coord, unsigned int width, unsigned int height ){ - return Coord2D( ( ( coord.x + 1.0f ) * 0.5f ) * width, ( ( coord.y + 1.0f ) * 0.5f ) * height ); -} - -inline rectangle_t rectangle_from_area( const float min[2], const float max[2], unsigned int width, unsigned int height ){ - Coord2D botleft( coord2d_device2screen( Coord2D( min[0], min[1] ), width, height ) ); - Coord2D topright( coord2d_device2screen( Coord2D( max[0], max[1] ), width, height ) ); - return rectangle_t( botleft.x, botleft.y, topright.x - botleft.x, topright.y - botleft.y ); -} - class XORRectangle { + void draw( const rect_t& rect, const GLenum mode ) const{ + glBegin( mode ); + glVertex2f( rect.min[0], rect.max[1] ); + glVertex2f( rect.max[0], rect.max[1] ); + glVertex2f( rect.max[0], rect.min[1] ); + glVertex2f( rect.min[0], rect.min[1] ); + glEnd(); + } public: XORRectangle() { } ~XORRectangle() { } - void set( rectangle_t rectangle, int width, int height ) { - if( rectangle.w != 0.f && rectangle.h != 0.f ) { + void set( rect_t rect, int width, int height ) { + if( rect.max[0] - rect.min[0] != 0.f && rect.max[1] - rect.min[1] != 0.f ) { GlobalOpenGL_debugAssertNoErrors(); glViewport( 0, 0, width, height ); // set up viewpoint glMatrixMode( GL_PROJECTION ); glLoadIdentity(); - glOrtho( 0, width, 0, height, -100, 100 ); + glOrtho( -1, 1, -1, 1, -100, 100 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); @@ -95,30 +61,41 @@ public: } glEnable( GL_BLEND ); + /* additive to handle dark background */ glBlendFunc( GL_ONE, GL_ONE ); - //glColor4f( 0.94902f / 5.f, 0.396078f / 5.f, 0.133333f / 5.f, .2f ); - glColor3f( 1.f / 10.f, .5f / 10.f, 0.f ); - - glBegin( GL_QUADS ); - glVertex2f( rectangle.x, rectangle.y + rectangle.h ); - glVertex2f( rectangle.x + rectangle.w, rectangle.y + rectangle.h ); - glVertex2f( rectangle.x + rectangle.w, rectangle.y ); - glVertex2f( rectangle.x, rectangle.y ); - glEnd(); + const float r = 10.f; + switch ( rect.modifier ) + { + case rect_t::eSelect: glColor3f( 1.f / r, .5f / r, 0.f ); break; + case rect_t::eDeselect: glColor3f( 0.f, 0.f, 1.f / r ); break; + case rect_t::eToggle: glColor3f( 1.f / r, 1.f / r, 1.f / r ); break; + } + draw( rect, GL_QUADS ); + /* filter to handle bright background */ + glBlendFunc( GL_ZERO, GL_SRC_COLOR ); + switch ( rect.modifier ) + { + case rect_t::eSelect: glColor3f( 1.f, .9f, 0.7f ); break; + case rect_t::eDeselect: glColor3f( 0.8f, 0.8f, 1.f ); break; + case rect_t::eToggle: glColor3f( .8f, .8f, .8f ); break; + } + draw( rect, GL_QUADS ); + /* alpha blend on top */ + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + const float a = .3f; + switch ( rect.modifier ) + { + case rect_t::eSelect: glColor4f( 1.f, .5f, 0.f, a ); break; + case rect_t::eDeselect: glColor4f( 0.f, 0.f, 1.f, a ); break; + case rect_t::eToggle: glColor4f( 1.f, 1.f, 1.f, a ); break; + } + draw( rect, GL_QUADS ); glDisable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - glLineWidth( 1 ); - //glColor3f( 0.94902f, 0.396078f, 0.133333f ); glColor3f( 1.f, .5f, 0.f ); - - glBegin( GL_LINE_LOOP ); - glVertex2f( rectangle.x, rectangle.y + rectangle.h ); - glVertex2f( rectangle.x + rectangle.w, rectangle.y + rectangle.h ); - glVertex2f( rectangle.x + rectangle.w, rectangle.y ); - glVertex2f( rectangle.x, rectangle.y ); - glEnd(); + draw( rect, GL_LINE_LOOP ); GlobalOpenGL_debugAssertNoErrors(); } diff --git a/libs/rect_t.cpp b/libs/rect_t.cpp new file mode 100644 index 00000000..26cb2542 --- /dev/null +++ b/libs/rect_t.cpp @@ -0,0 +1,22 @@ +/* + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. + + This file is part of GtkRadiant. + + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "rect_t.h" diff --git a/libs/rect_t.h b/libs/rect_t.h new file mode 100644 index 00000000..297b0a81 --- /dev/null +++ b/libs/rect_t.h @@ -0,0 +1,22 @@ +#if !defined( INCLUDED_RECT_T_H ) +#define INCLUDED_RECT_T_H + +struct rect_t { + float min[2]; + float max[2]; + + enum EModifier { + eSelect, + eDeselect, + eToggle, + }; + EModifier modifier; + + rect_t(){ + min[0] = min[1] = max[0] = max[1] = 0; + modifier = eSelect; + } +}; + + +#endif diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index cb5152eb..e3688a07 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -974,7 +974,7 @@ void camwnd_update_xor_rectangle( CamWnd& self, rect_t area ){ glDrawBuffer( GL_FRONT ); self.fbo_get()->blit(); - self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.getCamera().width, self.getCamera().height ), self.getCamera().width, self.getCamera().height ); + self.m_XORRectangle.set( area, self.getCamera().width, self.getCamera().height ); glDrawBuffer( GL_BACK ); @@ -1867,7 +1867,7 @@ void CamWnd::draw(){ GlobalOpenGL_debugAssertNoErrors(); //qglFinish(); - //m_XORRectangle.set( rectangle_t() ); + //m_XORRectangle.set( rect_t() ); } glwidget_swap_buffers( m_gl_widget ); diff --git a/radiant/selection.cpp b/radiant/selection.cpp index e8d4b7d4..13748437 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -3092,6 +3092,11 @@ inline const rect_t SelectionBoxForArea( const float device_point[2], const floa selection_box.min[1] = ( device_delta[1] < 0 ) ? ( device_point[1] + device_delta[1] ) : ( device_point[1] ); selection_box.max[0] = ( device_delta[0] > 0 ) ? ( device_point[0] + device_delta[0] ) : ( device_point[0] ); selection_box.max[1] = ( device_delta[1] > 0 ) ? ( device_point[1] + device_delta[1] ) : ( device_point[1] ); + selection_box.modifier = device_delta[0] * device_delta[1] < 0? + rect_t::eToggle + : device_delta[0] < 0 ? + rect_t::eDeselect + : rect_t::eSelect; return selection_box; } #if 0 @@ -4306,7 +4311,6 @@ public: enum EModifier { eManipulator, - eToggle, eReplace, eCycle, eSelect, @@ -4670,18 +4674,6 @@ void SelectPoint( const View& view, const float device_point[2], const float dev if ( !selector.failed() ) { switch ( modifier ) { - case RadiantSelectionSystem::eToggle: - { - SelectionPool::iterator best = selector.begin(); - // toggle selection of the object with least depth - if ( ( *best ).second->isSelected() ) { - ( *best ).second->setSelected( false ); - } - else{ - ( *best ).second->setSelected( true ); - } - } - break; // if cycle mode not enabled, enable it case RadiantSelectionSystem::eReplace: { @@ -4793,33 +4785,26 @@ bool SelectPoint_InitPaint( const View& view, const float device_point[2], const } } -void SelectArea( const View& view, const float device_point[2], const float device_delta[2], RadiantSelectionSystem::EModifier modifier, bool face ){ - if ( modifier == eReplace ) { - deselectComponentsOrAll( face ); - } - +void SelectArea( const View& view, const rect_t rect, bool face ){ #if defined ( DEBUG_SELECTION ) g_render_clipped.destroy(); #endif + View scissored( view ); + ConstructSelectionTest( scissored, rect ); + SelectionVolume volume( scissored ); + SelectionPool pool; + if ( face ) { + Scene_TestSelect_Component( pool, volume, scissored, eFace ); + } + else { - View scissored( view ); - ConstructSelectionTest( scissored, SelectionBoxForArea( device_point, device_delta ) ); + Scene_TestSelect( pool, volume, scissored, Mode(), ComponentMode() ); + } - SelectionVolume volume( scissored ); - SelectionPool pool; - if ( face ) { - Scene_TestSelect_Component( pool, volume, scissored, eFace ); - } - else - { - Scene_TestSelect( pool, volume, scissored, Mode(), ComponentMode() ); - } - - for ( SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i ) - { - ( *i ).second->setSelected( !( modifier == RadiantSelectionSystem::eToggle && ( *i ).second->isSelected() ) ); - } + for ( SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i ) + { + ( *i ).second->setSelected( rect.modifier == rect_t::eSelect? true : rect.modifier == rect_t::eDeselect? false : !( *i ).second->isSelected() ); } } @@ -5624,27 +5609,19 @@ typedef MemberCaller1 class Selector_ { RadiantSelectionSystem::EModifier modifier_for_state( ModifierFlags state ){ - if ( ( state == c_modifier_toggle || state == c_modifier_toggle_face || state == c_modifier_face || state == c_modifierAlt ) ) { - if( m_mouse2 ){ - return RadiantSelectionSystem::eReplace; - } - else{ - return RadiantSelectionSystem::eToggle; - } - } - return RadiantSelectionSystem::eManipulator; + if ( ( state == c_modifier_toggle || state == c_modifier_toggle_face || state == c_modifier_face ) + && m_mouse2 ) + return RadiantSelectionSystem::eReplace; + else + return RadiantSelectionSystem::eManipulator; } rect_t getDeviceArea() const { const DeviceVector delta( m_current - m_start ); - if ( m_mouseMovedWhilePressed && selecting() && delta.x() != 0 && delta.y() != 0 ) { + if ( m_mouseMovedWhilePressed && selecting() && delta.x() != 0 && delta.y() != 0 ) return SelectionBoxForArea( &m_start[0], &delta[0] ); - } else - { - rect_t default_area = { { 0, 0, }, { 0, 0, }, }; - return default_area; - } + return rect_t(); } const DeviceVector& m_epsilon; @@ -5678,7 +5655,7 @@ void testSelect( DeviceVector position ){ if ( modifier != RadiantSelectionSystem::eManipulator ) { const DeviceVector delta( position - m_start ); if ( m_mouseMovedWhilePressed && delta.x() != 0 && delta.y() != 0 ) { - getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], RadiantSelectionSystem::eToggle, ( m_state & c_modifier_face ) != c_modifierNone ); + getSelectionSystem().SelectArea( *m_view, SelectionBoxForArea( &m_start[0], &delta[0] ), ( m_state & c_modifier_face ) != c_modifierNone ); } else if( !m_mouseMovedWhilePressed ){ if ( modifier == RadiantSelectionSystem::eReplace && !m_mouseMoved ) { diff --git a/radiant/selection.h b/radiant/selection.h index 2146e461..01c7d599 100644 --- a/radiant/selection.h +++ b/radiant/selection.h @@ -24,12 +24,7 @@ #include "windowobserver.h" #include "generic/callbackfwd.h" - -struct rect_t -{ - float min[2]; - float max[2]; -}; +#include "rect_t.h" typedef Callback1 RectangleCallback; diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 809b0029..0ea69865 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -505,7 +505,7 @@ void XYWnd::XY_Draw_Overlay_finish(){ 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.m_XORRectangle.set( area, self.Width(), self.Height() ); self.XY_Draw_Overlay_finish(); } } @@ -588,7 +588,7 @@ gboolean xywnd_expose( GtkWidget* widget, GdkEventExpose* event, XYWnd* xywnd ){ xywnd->XY_Draw(); GlobalOpenGL_debugAssertNoErrors(); - //xywnd->m_XORRectangle.set( rectangle_t() ); + //xywnd->m_XORRectangle.set( rect_t() ); } glwidget_swap_buffers( xywnd->GetWidget() ); }