diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf2/commanderoverlaypanel.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf2/commanderoverlaypanel.cpp')
| -rw-r--r-- | game/client/tf2/commanderoverlaypanel.cpp | 1018 |
1 files changed, 1018 insertions, 0 deletions
diff --git a/game/client/tf2/commanderoverlaypanel.cpp b/game/client/tf2/commanderoverlaypanel.cpp new file mode 100644 index 0000000..5ef2914 --- /dev/null +++ b/game/client/tf2/commanderoverlaypanel.cpp @@ -0,0 +1,1018 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +//----------------------------------------------------------------------------- +// The panel responsible for rendering the 3D view in orthographic mode +//----------------------------------------------------------------------------- +#include "cbase.h" +#include <vgui/VGUI.h> +#include <vgui_controls/Controls.h> +#include <vgui/IVGui.h> +#include <vgui/IInput.h> +#include <vgui/ISurface.h> +#include "clientmode_commander.h" +#include "vgui_int.h" +#include "iinput.h" +#include "kbutton.h" +#include "hud_minimap.h" +#include "usercmd.h" +#include "mapdata.h" +#include "c_basetfplayer.h" +#include "view.h" +#include "view_shared.h" +#include "CommanderOverlay.h" +#include "C_TfTeam.h" +#include <vgui/MouseCode.h> +#include <vgui/KeyCode.h> +#include <vgui/IPanel.h> +#include "commanderoverlaypanel.h" +#include "PixelWriter.h" +#include "materialsystem/imaterialvar.h" +#include "materialsystem/itexture.h" +#include "vtf/vtf.h" +#include "engine/ivdebugoverlay.h" + + +static inline int AlphaMapIndex(int x, int y) +{ + return y * FOG_ALPHAMAP_SIZE + x; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *commander - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::SetCommanderView( CClientModeCommander *commander ) +{ + m_pCommanderView = commander; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCommanderOverlayPanel::CCommanderOverlayPanel( void ) : + vgui::Panel( NULL, "CommanderOverlayPanel" ), + m_CursorCommander(vgui::dc_arrow), + m_CursorRightMouseMove(vgui::dc_hand) +{ + MakePopup(); + + SetPaintBackgroundEnabled( false ); + m_left.m_bMouseDown = false; + m_left.m_nXStart = 0; + m_left.m_nYStart = 0; + + m_right.m_bMouseDown = false; + m_right.m_nXStart = 0; + m_right.m_nYStart = 0; + + m_fZoom = 0; + + m_flPreviousMaxWorldWidth = 0.0f; + SetVisible( false ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCommanderOverlayPanel::~CCommanderOverlayPanel( void ) +{ +} + + +//----------------------------------------------------------------------------- +// Initialize rendering origin +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::InitializeRenderOrigin() +{ + // Initializes the rendering origin + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + if ( player ) + { + m_vecTacticalOrigin = player->GetAbsOrigin(); + } + else + { + MapData().GetMapOrigin( m_vecTacticalOrigin ); + } + + Vector mins, maxs; + MapData().GetMapBounds( mins, maxs ); + m_vecTacticalOrigin.z = maxs.z + TACTICAL_ZOFFSET; + m_vecTacticalAngles.Init( 90, 90, 0 ); + BoundOrigin( m_vecTacticalOrigin ); +} + + +//----------------------------------------------------------------------------- +// Computes the view range: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::ComputeZoomRange() +{ + // This is + m_MinWorldWidth = TACTICAL_MIN_VIEWABLE_SIZE; + + // Get the world size + Vector mins, maxs, size; + MapData().GetMapBounds( mins, maxs ); + VectorSubtract( maxs, mins, size ); + float worldAspect = size[0] / size[1]; + +// size[ 0 ] *= 1.05f; +// size[ 1 ] *= 1.05f; + + // Find out the panel aspect ratio + int w, h; + GetVisibleSize( w, h ); + + float panelAspect = (float)w / (float)h; + + // Store off old zoom + m_flPreviousMaxWorldWidth = m_MaxWorldWidth; + + if (panelAspect > worldAspect) + { + // In this case, to see the whole map, + // we'll have black areas on the left + right sides + // Make sure we choose a width big enough to display the entire height + m_MaxWorldWidth = size[1] * panelAspect; + } + else + { + // In this case, to see the whole map, + // we'll have black areas on the top + bottom + // Make sure we choose a width big enough to display the entire height + m_MaxWorldWidth = size[0]; + } + + // if flipping open/close the tech tree, preserver relative zoom amount + if ( m_flPreviousMaxWorldWidth ) + { + float ratio = m_MaxWorldWidth / m_flPreviousMaxWorldWidth; + + m_fZoom *= ratio; + } +} + +//----------------------------------------------------------------------------- +// Call when the map changes +//----------------------------------------------------------------------------- + +void CCommanderOverlayPanel::LevelInit( char const* pMapName ) +{ + // Always look at the entire map to start with + m_fZoom = 0; + m_flPreviousMaxWorldWidth = 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::LevelShutdown( void ) +{ +} + +//----------------------------------------------------------------------------- +// call these when commander view is enabled/disabled +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::Enable() +{ + vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel(); + + SetCursor(m_CursorCommander); + SetVisible( true ); + + // Make the viewport fill the root panel. + if( pRoot) + { + int wide, tall; + vgui::ipanel()->GetSize(pRoot, wide, tall); + + // subtract out the technology UI size + tall -= 0;// xxx200 + + SetBounds(0, 0, wide, tall); + } + + // Cache the orthographic view size range + ComputeZoomRange(); + + // Start out looking at the whole world + if (m_fZoom == 0) + m_fZoom = m_MaxWorldWidth; + + // clamp + if (m_fZoom < m_MinWorldWidth) + m_fZoom = m_MinWorldWidth; + else if (m_fZoom > m_MaxWorldWidth) + m_fZoom = m_MaxWorldWidth; + + // Figure out where the camera is + InitializeRenderOrigin(); + + vgui::ivgui()->AddTickSignal( GetVPanel() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::Disable() +{ + SetVisible( false ); + // FIXME: Need a removeTickSignal! +// vgui::ivgui()->removeTickSignal( GetVPanel() ); +} + + +//----------------------------------------------------------------------------- +// called when we're ticked... +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::OnTick() +{ + if (!IsLocalPlayerInTactical() || !engine->IsInGame()) + return; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns up to 32 players encoded as a bit per player in a 32 bit unsigned +// Output : unsigned int +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::GetSelectedPlayerBitField( CBitVec< MAX_PLAYERS >& bits ) +{ + CMapPlayers *pPlayer; + + bits.ClearAll(); + + // draw all the visible players + for ( int playerNum = 0; playerNum < MAX_PLAYERS; playerNum++ ) + { + pPlayer = &MapData().m_Players[ playerNum ]; + if ( pPlayer->m_bSelected ) + { + bits.Set( playerNum ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Counts how many players are selected +// Output : int +//----------------------------------------------------------------------------- +int CCommanderOverlayPanel::CountSelectedPlayers( void ) +{ + CMapPlayers *pPlayer; + + // bitfield variable + int count = 0; + + // draw all the visible players + for ( int playerNum = 0; playerNum < MAX_PLAYERS; playerNum++ ) + { + pPlayer = &MapData().m_Players[ playerNum ]; + if ( pPlayer->m_bSelected ) + { + count++; + } + } + + return count; +} + +//----------------------------------------------------------------------------- +// Purpose: Called when a key is pressed +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::OnKeyPressed(vgui::KeyCode code) +{ + switch(code) + { + case vgui::KEY_SPACE: + if (m_fZoom != m_MaxWorldWidth) + { + ChangeZoomLevel(m_MaxWorldWidth); + } + else + { + Vector mouseWorldPos; + CenterOnMouse( mouseWorldPos ); + + ChangeZoomLevel(TACTICAL_SPACEBAR_VIEWABLE_SIZE); + + // Place mouse over me + m_pCommanderView->MoveMouse( mouseWorldPos ); + } + break; + + default: + break; + } +} + +//----------------------------------------------------------------------------- +// Purpose: when space is hit, show the entire view +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::ChangeZoomLevel( float newZoom ) +{ + // Make sure the mouse remains over the thing it started over + + // Figure out worldspace movement based on picking ray + Vector rayOrigin, rayForward; + + int mx, my; + GetMousePos( mx, my ); + + // Need to convert from screen space back to a worldspace ray + CreatePickingRay( + mx, my, + ScreenWidth(), ScreenHeight(), + CurrentViewOrigin(), + CurrentViewAngles(), + rayOrigin, + rayForward ); + + m_fZoom = newZoom; + + BoundOrigin( m_vecTacticalOrigin ); + + // move mouse to center and zero out any delta + m_pCommanderView->MoveMouse( rayOrigin ); +// RequestFocus(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CCommanderOverlayPanel::IsRightMouseMapMoving( void ) +{ + return m_right.m_bMouseDown; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::RightMouseMapMove( void ) +{ + /* + // Figure out worldspace movement based on picking ray + Vector rayForward; + Vector vecEndPosCurrent, vecEndPosPrevious; + + // Need to convert from screen space back to a worldspace ray + CreatePickingRay( + m_right.m_nXCurrent, m_right.m_nYCurrent, + ScreenWidth(), ScreenHeight(), + g_vecRenderOrigin, + g_vecRenderAngles, + vecEndPosCurrent, + rayForward ); + + engine->Con_NPrintf( 8, "x %i y %i hit %.3f %.3f", + m_right.m_nXCurrent, m_right.m_nYCurrent, vecEndPosCurrent.x, vecEndPosCurrent.y ); + */ + + if ( !m_right.m_bMouseDown ) + return; + + /* + // See if there is a delta in the current and previous mouse positions + // + int dx, dy; + + dx = m_right.m_nXCurrent - m_right.m_nXPrev; + dy = m_right.m_nYCurrent - m_right.m_nYPrev; + + // No relative move + if ( !dx && !dy ) + return; + + // Figure out worldspace movement based on picking ray + Vector rayForward; + Vector vecEndPosCurrent, vecEndPosPrevious; + + // Need to convert from screen space back to a worldspace ray + CreatePickingRay( + m_right.m_nXCurrent, m_right.m_nYCurrent, + ScreenWidth(), ScreenHeight(), + g_vecRenderOrigin, + g_vecRenderAngles, + vecEndPosCurrent, + rayForward ); + + // Now create ray from old position + // Need to convert from screen space back to a worldspace ray + CreatePickingRay( + m_right.m_nXPrev, m_right.m_nYPrev, + ScreenWidth(), ScreenHeight(), + g_vecRenderOrigin, + g_vecRenderAngles, + vecEndPosPrevious, + rayForward ); + + // Remove z component + vecEndPosPrevious.z = 0.0; + vecEndPosCurrent.z = 0.0; + + // Compute offset + Vector viewDelta; + VectorSubtract( vecEndPosCurrent, vecEndPosPrevious, viewDelta ); + + viewDelta.z = 0.0f; + + VectorAdd( m_vecTacticalOrigin, viewDelta, m_vecTacticalOrigin ); + + m_pCommanderView->BoundOrigin( m_vecTacticalOrigin ); + */ +} + + +//----------------------------------------------------------------------------- +// Purpose: Right mouse button down +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::RightMousePressed( void ) +{ + if ( m_left.m_bMouseDown || m_right.m_bMouseDown ) + return; + + SetCursor(m_CursorRightMouseMove); + + StartMovingMouse( m_right ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::RightMouseReleased( void ) +{ + if ( !m_right.m_bMouseDown ) + return; + + m_right.m_bMouseDown = false; + int mx, my; + GetMousePos( mx, my ); + UpdateMousePos( mx, my, m_right ); + + // Final move + RightMouseMapMove(); + + vgui::input()->SetMouseCapture( NULL ); + + SetCursor(m_CursorCommander); + + // If the player's dead, and doesn't have the special sniper upgrade + // then check for respawn stations.... + C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer(); + if (!pPlayer) + return; + + // If the player's dead, abort + if ( pPlayer->PlayerClass() == TFCLASS_SNIPER ) + { + // Sniper's can request a respawn point when dead + // + Vector rayOrigin, rayForward; + Vector vecEndPos; + + // Need to convert from screen space back to a worldspace ray + CreatePickingRay( + m_right.m_nXCurrent, m_right.m_nYCurrent, + ScreenWidth(), ScreenHeight(), + CurrentViewOrigin(), + CurrentViewAngles(), + rayOrigin, + rayForward ); + + // Now do the trace + trace_t tr; + + vecEndPos = rayOrigin + rayForward * MAX_TRACE_LENGTH; + + UTIL_TraceLine( rayOrigin, vecEndPos, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); + + // Didn't hit anything + if ( tr.fraction == 1.0 ) + return; + + char cmd[ 128 ]; + Q_snprintf( cmd, sizeof( cmd ), "respawnpoint %i %i %i\n", + (int)tr.endpos.x, + (int)tr.endpos.y, + (int)tr.endpos.z ); + + engine->ServerCmd( cmd ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : x - +// y - +// mouse - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::UpdateMousePos( int x, int y, MouseDown_t& mouse ) +{ + // store previous + mouse.m_nXPrev = mouse.m_nXCurrent; + mouse.m_nYPrev = mouse.m_nYCurrent; + // update current + mouse.m_nXCurrent = x; + mouse.m_nYCurrent = y; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : x - +// y - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::OnCursorMoved(int x, int y) +{ + UpdateMousePos( x, y, m_left ); + UpdateMousePos( x, y, m_right ); + + RightMouseMapMove(); +// RequestFocus(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : x - +// y - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::GetMousePos( int& x, int& y ) +{ + vgui::input()->GetCursorPos( x, y ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : mouse - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::StartMovingMouse( MouseDown_t& mouse ) +{ + mouse.m_bMouseDown = true; + GetMousePos( mouse.m_nXStart, mouse.m_nYStart ); + + mouse.m_nXCurrent = mouse.m_nXPrev = mouse.m_nXStart; + mouse.m_nYCurrent = mouse.m_nYPrev = mouse.m_nYStart; + + vgui::input()->SetMouseCapture( GetVPanel() ); +} + +//----------------------------------------------------------------------------- +// Purpose: Left mouse button down +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::LeftMousePressed( void ) +{ + if ( m_left.m_bMouseDown || m_right.m_bMouseDown ) + return; + + StartMovingMouse( m_left ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : code - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::OnMousePressed(vgui::MouseCode code) +{ + switch ( code ) + { + case vgui::MOUSE_LEFT: + LeftMousePressed(); + break; + case vgui::MOUSE_RIGHT: + RightMousePressed(); + break; + default: + BaseClass::OnMousePressed( code ); + return; + } + +// RequestFocus(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : x0 - +// y0 - +// x1 - +// y1 - +// true - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::SelectPlayersInRectangle( int x0, int y0, int x1, int y1, bool clearOldSelections /*= true*/ ) +{ + int num_selected = 0; + + // Assume zero players in selection + if ( clearOldSelections ) + { + m_bHaveActiveSelection = false; + } + else + { + // Count # selected + num_selected = CountSelectedPlayers(); + } + + CMapPlayers *pPlayer; + C_BaseTFPlayer *tf2player; + + // See which players on my team are within the rectangle in screen space + // + for ( int playerNum = 1; playerNum <= MAX_PLAYERS; playerNum++ ) + { + pPlayer = &MapData().m_Players[ playerNum - 1 ]; + + if ( clearOldSelections ) + { + pPlayer->m_bSelected = false; + } + + if ( playerNum > gpGlobals->maxClients ) + { + continue; + } + + tf2player = dynamic_cast<C_BaseTFPlayer *>( cl_entitylist->GetEnt( playerNum ) ); + if ( !tf2player ) + { + continue; + } + + // Check pvs on this guy + // If the entity was in the commander's PVS then show it on the minimap, too + // + if ( ArePlayersOnSameTeam( engine->GetLocalPlayer(), playerNum ) == false ) + { + continue; + } + + // Check their actual draw position + int drawX, drawY; + Vector pos, screen; + + pos = tf2player->GetAbsOrigin(); + + // Transform + debugoverlay->ScreenPosition( pos, screen ); + + // FIXME: Get the player icon size from where?!? + drawX = screen.x - 32; + drawY = screen.y - 40; + int intersectX = 64; + int intersectY = 64; + + // Check for intersection ( with slop ) + if ( drawX + intersectX < x0 ) + continue; + if ( drawX > x1 ) + continue; + if ( drawY + intersectY < y0 ) + continue; + if ( drawY > y1 ) + continue; + + // Already selected? + if ( !pPlayer->m_bSelected ) + { + // Add to selected list + pPlayer->m_bSelected = true; + num_selected++; + } + } + + if ( num_selected != 0 ) + { + m_bHaveActiveSelection = true; + } +} + +//----------------------------------------------------------------------------- +// Returns the visible area (not including the tech tree) +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::GetVisibleSize( int& w, int& h ) +{ + GetSize( w, h ); + + // FIXME: Hack to make the map appear above the tech tree + h -= 200; +} + +//----------------------------------------------------------------------------- +// Returns the visible area (not including the tech tree) +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::GetVisibleArea( Vector& mins, Vector& maxs ) +{ + float w, h; + GetVisibleOrthoSize( w, h ); + + ActualToVisibleOffset( mins ); + mins += m_vecTacticalOrigin; + maxs = mins; + mins.x -= w; maxs.x +=w; + mins.y -= h; maxs.y +=h; +} + +//----------------------------------------------------------------------------- +// Purpose: User let go of left mouse button +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::LeftMouseReleased( void ) +{ + if ( !m_left.m_bMouseDown ) + return; + + m_left.m_bMouseDown = false; + + int mx, my; + GetMousePos( mx, my ); + UpdateMousePos( mx, my, m_left ); + + vgui::input()->SetMouseCapture( NULL ); + + // Normalize the rectangle + int x0, y0, x1, y1; + x0 = MIN( m_left.m_nXStart, m_left.m_nXCurrent ); + x1 = MAX( m_left.m_nXStart, m_left.m_nXCurrent ); + y0 = MIN( m_left.m_nYStart, m_left.m_nYCurrent ); + y1 = MAX( m_left.m_nYStart, m_left.m_nYCurrent ); + + bool clearOldStates = true; + if ( vgui::input()->IsKeyDown( vgui::KEY_LCONTROL ) ) + { + clearOldStates = false; + } + + SelectPlayersInRectangle( x0, y0, x1, y1, clearOldStates ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::GetOrthoRenderBox(Vector &vCenter, float &xSize, float &ySize) +{ + vCenter = m_vecTacticalOrigin; + + // min and max depends on the current zoom level + int w, h; + GetParent()->GetSize( w, h ); + + xSize = m_fZoom; + ySize = xSize * ( (float)h / (float)w ); + + xSize *= 0.5f; + ySize *= 0.5f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::GetVisibleOrthoSize(float &xSize, float &ySize) +{ + // min and max depends on the current zoom level + int w, h; + GetVisibleSize( w, h ); + xSize = m_fZoom; + ySize = xSize * ( (float)h / (float)w ); + + xSize *= 0.5f; + ySize *= 0.5f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CCommanderOverlayPanel::WorldUnitsPerPixel() +{ + int w, h; + GetParent()->GetSize( w, h ); + return m_fZoom / w; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::ActualToVisibleOffset( Vector& offset ) +{ + // FIXME: This doesn't work arbitrarily; we assume the visible + // part is on the top of the screen.. + int w, h, wact, hact; + GetVisibleSize( w, h ); + GetParent()->GetSize( wact, hact ); + + float worldUnitsPerPixel = m_fZoom / wact; + float dWorldY = (hact - h) * 0.5f * worldUnitsPerPixel; + offset.Init( 0, dWorldY, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: Make sure origin is inside map x, y bounds ( not z ) +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::BoundOrigin( Vector& camera ) +{ + // We're going to do this entire computation assuming the camera + // is in the center of the viewable area, which it isn't. At the + // end, we'll need to apply a fixup to deal with that + + Vector mins, maxs, halfsize; + MapData().GetMapBounds( mins, maxs ); + VectorSubtract( maxs, mins, halfsize ); + halfsize *= 0.5f; + + // avoid black edges... + float dim[2]; + GetVisibleOrthoSize( dim[0], dim[1] ); + + // Compute the position of the center of the visible area based on + // the new suggested camera position + Vector actualToVisible, newVisCenter; + ActualToVisibleOffset( actualToVisible ); + VectorAdd( camera, actualToVisible, newVisCenter ); + + // Only bound x & y + for ( int i = 0; i < 2; i++ ) + { + if (dim[i] > halfsize[i]) + { + newVisCenter[i] = mins[i] + halfsize[i]; + } + else + { + newVisCenter[ i ] = MAX( newVisCenter[i], mins[i] + dim[i] ); + newVisCenter[ i ] = MIN( newVisCenter[i], maxs[i] - dim[i] ); + } + } + + // Remember: The viewport takes up the entire screen; but the visible + // area only takes up the top half of the screen. Therefore, we need to + // set the origin so that the center of what we want lies at the + // center of the visible region + VectorSubtract( newVisCenter, actualToVisible, camera ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Given mouse/screen positions as well as the current +// render origin and angles, returns a unit vector through the mouse position +// that can be used to trace into the world under the mouse click pixel. +// Input : fov - +// mousex - +// mousey - +// screenwidth - +// screenheight - +// vecRenderAngles - +// c_x - +// vpn - +// vup - +// 360.0 - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::CreatePickingRay( int mousex, int mousey, + int screenwidth, int screenheight, + const Vector& vecRenderOrigin, + const QAngle& vecRenderAngles, + Vector &rayOrigin, + Vector &rayDirection + ) +{ + Vector vCenter; + float xSize, ySize; + GetOrthoRenderBox(vCenter, xSize, ySize); + + float xPos = RemapVal(mousex, 0, screenwidth, vCenter.x-xSize, vCenter.x+xSize); + float yPos = RemapVal(mousey, 0, screenheight, vCenter.y+ySize, vCenter.y-ySize); // (flip screen y) + rayOrigin.Init(xPos, yPos, vCenter.z); + rayDirection.Init(0, 0, -1); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::OnMouseReleased(vgui::MouseCode code) +{ + switch ( code ) + { + case vgui::MOUSE_LEFT: + LeftMouseReleased(); + break; + case vgui::MOUSE_RIGHT: + RightMouseReleased(); + break; + default: + BaseClass::OnMouseReleased( code ); + return; + } + +// RequestFocus(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::CenterOnMouse( Vector& mouseWorldPos ) +{ + // Figure out worldspace movement based on picking ray + Vector rayForward; + Vector centerOrigin; + + int mx, my; + GetMousePos( mx, my ); + + // Need to convert from screen space back to a worldspace ray + CreatePickingRay( + mx, my, + ScreenWidth(), ScreenHeight(), + CurrentViewOrigin(), + CurrentViewAngles(), + mouseWorldPos, + rayForward ); + + CreatePickingRay( + ScreenWidth()/2, ScreenHeight()/2, + ScreenWidth(), ScreenHeight(), + CurrentViewOrigin(), + CurrentViewAngles(), + centerOrigin, + rayForward ); + + Vector offset; + VectorSubtract( mouseWorldPos, centerOrigin, offset ); + offset.z = 0.0f; + VectorAdd( m_vecTacticalOrigin, offset, m_vecTacticalOrigin ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : delta - +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::OnMouseWheeled(int delta) +{ + // Figure out worldspace movement based on picking ray + Vector rayOrigin; + + CenterOnMouse( rayOrigin ); + + // Gotta do the zoom after picking the ray, or it'll use the wrong zoom factor + // for computing the picking ray + if ( delta < 0 ) + { + m_fZoom *= 1.25f; + } + else if ( delta > 0 ) + { + m_fZoom /= 1.25f; + } + + m_fZoom = MIN( m_fZoom, m_MaxWorldWidth ); + m_fZoom = MAX( m_fZoom, m_MinWorldWidth ); + + BoundOrigin( m_vecTacticalOrigin ); + + // move mouse to center and zero out any delta + m_pCommanderView->MoveMouse( rayOrigin ); + +// RequestFocus(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCommanderOverlayPanel::Paint() +{ + if ( !m_left.m_bMouseDown ) + return; + + // Update mouse position, so we don't get the 1 frame lag + int mx, my; + GetMousePos( mx, my ); + UpdateMousePos( mx, my, m_left ); + + int x0, x1, y0, y1; + // Make sure it's normalized + x0 = MIN( m_left.m_nXStart, m_left.m_nXCurrent ); + x1 = MAX( m_left.m_nXStart, m_left.m_nXCurrent ); + y0 = MIN( m_left.m_nYStart, m_left.m_nYCurrent ); + y1 = MAX( m_left.m_nYStart, m_left.m_nYCurrent ); + + // Draw selection rectangle + vgui::surface()->DrawSetColor( 200, 220, 250, 192 ); + vgui::surface()->DrawOutlinedRect( x0, y0, x1, y1 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CCommanderOverlayPanel::GetZoom( void ) +{ + return (m_fZoom - m_MinWorldWidth) / (m_MaxWorldWidth - m_MinWorldWidth); +} |