quadrilateralcowboy/tools/guied/GESelectionMgr.cpp
2020-06-12 14:06:25 -07:00

474 lines
13 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../../renderer/tr_local.h"
#include "../../sys/win32/win_local.h"
#include "GEApp.h"
#include "GESelectionMgr.h"
#define GUIED_GRABSIZE 7
#define GUIED_CENTERSIZE 5
rvGESelectionMgr::rvGESelectionMgr ( )
{
mWorkspace = NULL;
}
/*
================
rvGESelectionMgr::SetSelection
Sets the only selection for the workspace to the given window
================
*/
void rvGESelectionMgr::Set ( idWindow* window )
{
// Get rid of any current selections
Clear ( );
// Add this selection now
return Add ( window );
}
/*
================
rvGESelectionMgr::Add
Adds the given window to the selection list
================
*/
void rvGESelectionMgr::Add ( idWindow* window, bool expand )
{
rvGEWindowWrapper* wrapper;
wrapper = rvGEWindowWrapper::GetWrapper ( window );
assert ( wrapper );
// If the window is already selected then dont add the selection
if ( wrapper->IsSelected ( ) )
{
return;
}
wrapper->SetSelected ( true );
mSelections.Append ( window );
if ( expand && wrapper->Expand ( ) )
{
gApp.GetNavigator ( ).Update ( );
}
gApp.GetNavigator ( ).UpdateSelections ( );
gApp.GetNavigator ( ).Refresh ( );
gApp.GetTransformer ( ).Update ( );
gApp.GetProperties().Update ( );
UpdateExpression ( );
}
/*
================
rvGESelectionMgr::RemoveSelection
Removes the selection from the current workspace
================
*/
void rvGESelectionMgr::Remove ( idWindow* window )
{
rvGEWindowWrapper* wrapper;
wrapper = rvGEWindowWrapper::GetWrapper ( window );
assert ( wrapper );
// Dont bother if the window isnt selectd already
if ( !wrapper->IsSelected ( ) )
{
return;
}
wrapper->SetSelected ( false );
mSelections.Remove ( window );
gApp.GetNavigator ( ).UpdateSelections ( );
gApp.GetNavigator ( ).Refresh ( );
gApp.GetTransformer ( ).Update ( );
gApp.GetProperties().Update ( );
UpdateExpression ( );
}
/*
================
rvGESelectionMgr::ClearSelections
Remove all of the current selections
================
*/
void rvGESelectionMgr::Clear ( void )
{
int i;
for ( i = 0; i < mSelections.Num ( ); i ++ )
{
rvGEWindowWrapper::GetWrapper ( mSelections[i] )->SetSelected ( false );
}
mSelections.Clear ( );
gApp.GetNavigator ( ).UpdateSelections ( );
gApp.GetNavigator ( ).Refresh ( );
gApp.GetTransformer ( ).Update ( );
gApp.GetProperties().Update ( );
mExpression = false;
}
/*
================
rvGESelectionMgr::Render
Render the selections including the move/size bars
================
*/
void rvGESelectionMgr::Render ( void )
{
if ( !mSelections.Num ( ) )
{
return;
}
qglEnable(GL_BLEND);
qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UpdateRectangle ( );
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE );
idVec4& color = gApp.GetOptions().GetSelectionColor ( );
qglColor4f ( color[0],color[1],color[2], 1.0f );
qglBegin(GL_LINE_LOOP );
qglVertex2f ( mRect.x, mRect.y );
qglVertex2f ( mRect.x + mRect.w, mRect.y );
qglVertex2f ( mRect.x + mRect.w, mRect.y + mRect.h);
qglVertex2f ( mRect.x, mRect.y + mRect.h);
qglEnd ( );
qglColor4f ( color[0],color[1],color[2], 0.75f );
int i;
for ( i = 0; i < mSelections.Num(); i ++ )
{
rvGEWindowWrapper* wrapper;
idRectangle rect;
wrapper = rvGEWindowWrapper::GetWrapper ( mSelections[i] );
assert ( wrapper );
rect = wrapper->GetScreenRect ( );
mWorkspace->WorkspaceToWindow ( rect );
if ( i == 0 )
{
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL );
qglBegin ( GL_TRIANGLES );
qglVertex2f ( rect.x, rect.y );
qglVertex2f ( rect.x + GUIED_GRABSIZE, rect.y );
qglVertex2f ( rect.x, rect.y + GUIED_GRABSIZE );
qglEnd ( );
}
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE );
qglBegin(GL_LINE_LOOP );
qglVertex2f ( rect.x, rect.y );
qglVertex2f ( rect.x + rect.w, rect.y );
qglVertex2f ( rect.x + rect.w, rect.y + rect.h);
qglVertex2f ( rect.x, rect.y + rect.h);
qglEnd ( );
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL );
qglBegin( GL_QUADS );
qglVertex2f ( rect.x + (rect.w - GUIED_CENTERSIZE) / 2, rect.y + (rect.h - GUIED_CENTERSIZE) / 2 );
qglVertex2f ( rect.x + (rect.w + GUIED_CENTERSIZE) / 2, rect.y + (rect.h - GUIED_CENTERSIZE) / 2 );
qglVertex2f ( rect.x + (rect.w + GUIED_CENTERSIZE) / 2, rect.y + (rect.h + GUIED_CENTERSIZE) / 2 );
qglVertex2f ( rect.x + (rect.w - GUIED_CENTERSIZE) / 2, rect.y + (rect.h + GUIED_CENTERSIZE) / 2 );
qglEnd ( );
}
if ( mExpression )
{
return;
}
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE );
qglColor4f ( color[0],color[1],color[2], 1.0f );
qglBegin(GL_QUADS);
// Top Left
qglVertex2f ( mRect.x - GUIED_GRABSIZE, mRect.y - GUIED_GRABSIZE );
qglVertex2f ( mRect.x - 1, mRect.y - GUIED_GRABSIZE );
qglVertex2f ( mRect.x - 1, mRect.y - 1 );
qglVertex2f ( mRect.x - GUIED_GRABSIZE, mRect.y - 1 );
// Left
qglVertex2f ( mRect.x - GUIED_GRABSIZE, mRect.y + mRect.h / 2 - GUIED_GRABSIZE / 2);
qglVertex2f ( mRect.x - 1, mRect.y + mRect.h / 2 - GUIED_GRABSIZE / 2 );
qglVertex2f ( mRect.x - 1, mRect.y + mRect.h / 2 + GUIED_GRABSIZE / 2 );
qglVertex2f ( mRect.x - GUIED_GRABSIZE, mRect.y + mRect.h / 2 + GUIED_GRABSIZE / 2 );
// Bototm Left
qglVertex2f ( mRect.x - GUIED_GRABSIZE, mRect.y + mRect.h + 1 );
qglVertex2f ( mRect.x - 1, mRect.y + mRect.h + 1 );
qglVertex2f ( mRect.x - 1, mRect.y + mRect.h + GUIED_GRABSIZE );
qglVertex2f ( mRect.x - GUIED_GRABSIZE, mRect.y + mRect.h + GUIED_GRABSIZE );
// Bottom
qglVertex2f ( mRect.x - GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y + mRect.h + 1 );
qglVertex2f ( mRect.x + GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y + mRect.h + 1 );
qglVertex2f ( mRect.x + GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y + mRect.h + GUIED_GRABSIZE );
qglVertex2f ( mRect.x - GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y + mRect.h + GUIED_GRABSIZE );
// Bottom Right
qglVertex2f ( mRect.x + mRect.w + 1, mRect.y + mRect.h + 1 );
qglVertex2f ( mRect.x + mRect.w + GUIED_GRABSIZE, mRect.y + mRect.h + 1 );
qglVertex2f ( mRect.x + mRect.w + GUIED_GRABSIZE, mRect.y + mRect.h + GUIED_GRABSIZE );
qglVertex2f ( mRect.x + mRect.w + 1, mRect.y + mRect.h + GUIED_GRABSIZE );
// Right
qglVertex2f ( mRect.x + mRect.w + 1, mRect.y + mRect.h / 2 - GUIED_GRABSIZE / 2);
qglVertex2f ( mRect.x + mRect.w + GUIED_GRABSIZE, mRect.y + mRect.h / 2 - GUIED_GRABSIZE / 2 );
qglVertex2f ( mRect.x + mRect.w + GUIED_GRABSIZE, mRect.y + mRect.h / 2 + GUIED_GRABSIZE / 2 );
qglVertex2f ( mRect.x + mRect.w + 1, mRect.y + mRect.h / 2 + GUIED_GRABSIZE / 2 );
// Top Right
qglVertex2f ( mRect.x + mRect.w + 1, mRect.y - GUIED_GRABSIZE );
qglVertex2f ( mRect.x + mRect.w + GUIED_GRABSIZE, mRect.y - GUIED_GRABSIZE );
qglVertex2f ( mRect.x + mRect.w + GUIED_GRABSIZE, mRect.y - 1 );
qglVertex2f ( mRect.x + mRect.w + 1, mRect.y - 1 );
// Top
qglVertex2f ( mRect.x - GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y - GUIED_GRABSIZE );
qglVertex2f ( mRect.x + GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y - GUIED_GRABSIZE );
qglVertex2f ( mRect.x + GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y - 1 );
qglVertex2f ( mRect.x - GUIED_GRABSIZE / 2 + mRect.w / 2, mRect.y - 1 );
qglEnd ( );
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL );
}
/*
================
rvGESelectionMgr::UpdateRectangle
Update the selection rectangle from all the currently selected items.
================
*/
void rvGESelectionMgr::UpdateRectangle ( void )
{
int i;
idVec2 point;
assert ( mWorkspace );
if ( mSelections.Num ( ) <= 0 )
{
return;
}
// Start with the first selections retangle
mRect = rvGEWindowWrapper::GetWrapper( mSelections[0] )->GetScreenRect ( );
// Its easier to do the calculates with it being top left and bottom right
// so temporarly convert width and height to right and bottom
mRect.w += mRect.x;
mRect.h += mRect.y;
// Merge all the rest of the rectangles to make the actual selection rectangle
for ( i = 1; i < mSelections.Num(); i ++ )
{
idRectangle selRect;
selRect = rvGEWindowWrapper::GetWrapper ( mSelections[i] )->GetScreenRect ( );
mRect.w = max(selRect.x+selRect.w,mRect.w);
mRect.h = max(selRect.y+selRect.h,mRect.h);
mRect.x = min(selRect.x,mRect.x);
mRect.y = min(selRect.y,mRect.y);
}
mRect.w -= mRect.x;
mRect.h -= mRect.y;
mWorkspace->WorkspaceToWindow ( mRect );
}
/*
================
rvGESelectionMgr::UpdateExpression
Update whether or not the selection has an expression in it
================
*/
void rvGESelectionMgr::UpdateExpression ( void )
{
int i;
mExpression = false;
for ( i = 0; i < mSelections.Num(); i ++ )
{
rvGEWindowWrapper* wrapper;
wrapper = rvGEWindowWrapper::GetWrapper ( mSelections[i] );
if ( wrapper && !wrapper->CanMoveAndSize ( ) )
{
mExpression = true;
break;
}
}
}
/*
================
rvGESelectionMgr::HitTest
Test to see if the given coordinate is within the selection rectangle and if it is
see what its over.
================
*/
rvGESelectionMgr::EHitTest rvGESelectionMgr::HitTest ( float x, float y )
{
if ( !mSelections.Num ( ) )
{
return HT_NONE;
}
UpdateRectangle ( );
// Inside the rectangle is moving
if ( mRect.Contains ( x, y ) )
{
return mExpression?HT_SELECT:HT_MOVE;
}
if ( mExpression )
{
return HT_NONE;
}
// Check for top left sizing
if ( idRectangle ( mRect.x - GUIED_GRABSIZE, mRect.y - GUIED_GRABSIZE, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_TOPLEFT;
}
// Check for left sizing
if ( idRectangle ( mRect.x - GUIED_GRABSIZE, mRect.y + mRect.h / 2 - GUIED_GRABSIZE / 2, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_LEFT;
}
// Check for bottom left sizing
if ( idRectangle ( mRect.x - GUIED_GRABSIZE, mRect.y + mRect.h, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_BOTTOMLEFT;
}
// Check for bottom sizing
if ( idRectangle ( mRect.x + mRect.w / 2 - GUIED_GRABSIZE / 2, mRect.y + mRect.h, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_BOTTOM;
}
// Check for bottom right sizing
if ( idRectangle ( mRect.x + mRect.w, mRect.y + mRect.h, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_BOTTOMRIGHT;
}
// Check for right sizing
if ( idRectangle ( mRect.x + mRect.w, mRect.y + mRect.h / 2 - GUIED_GRABSIZE / 2, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_RIGHT;
}
// Check for top right sizing
if ( idRectangle ( mRect.x + mRect.w, mRect.y - GUIED_GRABSIZE, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_TOPRIGHT;
}
// Check for top sizing
if ( idRectangle ( mRect.x + mRect.w / 2 - GUIED_GRABSIZE / 2, mRect.y - GUIED_GRABSIZE, GUIED_GRABSIZE, GUIED_GRABSIZE ).Contains ( x, y ) )
{
return HT_SIZE_TOP;
}
return HT_NONE;
}
/*
================
rvGESelectionMgr::GetBottomMost
Returns the bottom most selected window.
================
*/
idWindow* rvGESelectionMgr::GetBottomMost ( void )
{
idWindow* bottom;
int depth;
int i;
depth = 9999;
bottom = NULL;
// Loop through all the selections and find the bottom most window
for ( i = 0; i < mSelections.Num(); i ++ )
{
idWindow* parent;
int tempDepth;
// Calculate the depth of the window by iterating back through the windows parents
for ( tempDepth = 0, parent = mSelections[i]; parent; parent = parent->GetParent ( ), tempDepth++ );
// If the new depth is less than the current depth then this window is below
if ( tempDepth < depth )
{
depth = tempDepth;
bottom = mSelections[i];
}
}
return bottom;
}