etqw-sdk/source/game/structures/CommandMapPost.cpp
2008-05-29 00:00:00 +00:00

528 lines
15 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../precompiled.h"
#pragma hdrstop
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "CommandMapPost.h"
#include "../Player.h"
#include "../CommandMapInfo.h"
#include "../guis/UserInterfaceLocal.h"
#include "../guis/UIWindow.h"
#include "../../sys/sys_local.h"
/*
================
sdCommandMapPost::GetWorldToMapTransform
================
*/
void sdCommandMapPost::WorldToMapTransform( const idVec2& inverseSize, idVec2& coords, const idVec2& cameraPosition, const idVec2& screenExtents ) {
coords.x -= cameraPosition.x;
coords.x *= inverseSize.x;
coords.x *= screenExtents.x;
coords.x += screenExtents.x * 0.5f;
coords.y -= cameraPosition.y;
coords.y *= inverseSize.y;
coords.y *= -screenExtents.y;
coords.y += screenExtents.y * 0.5f;
}
/*
================
sdCommandMapPost::ClampMapCamera
================
*/
void sdCommandMapPost::ClampMapCamera( const idVec2& org, const idVec2& size, idVec2& cameraPosition, const sdBounds2D& bounds ) {
idVec2 scale = size * -0.5f;
cameraPosition.x = idMath::ClampFloat( bounds[ 0 ].x - scale.x, bounds[ 1 ].x + scale.x, org.x );
cameraPosition.y = idMath::ClampFloat( bounds[ 0 ].y - scale.y, bounds[ 1 ].y + scale.y, org.y );
}
/*
================
sdCommandMapPost::HandleLocalPlayerCommandMapInput
================
*/
bool sdCommandMapPost::HandleLocalPlayerCommandMapInput( sdUIWindow* window, const sdSysEvent* event ) {
idPlayer* player = gameLocal.GetLocalPlayer();
if ( player == NULL ) {
return false;
}
if ( !event->IsMouseButtonEvent() || event->GetMouseButton() != M_MOUSE1 || !event->IsButtonDown() ) {
return false;
}
const idVec4& rect = window->GetWorldRect();
idVec2 screenPos( rect.x, rect.y );
idVec2 screenExtents( rect.z, rect.w );
float scale = 1.f;
// jrad - allow local overrides for vehicle cockpits, warroom maps, etc
sdProperties::sdProperty* prop = window->GetUI()->GetState().GetProperty( "mapZoomLevel", sdProperties::PT_FLOAT );
if( !prop ) {
sdUserInterfaceScope* scope = gameLocal.globalProperties.GetSubScope( "gameHud" );
if( scope ) {
prop = scope->GetProperty( "mapZoomLevel", sdProperties::PT_FLOAT );
}
}
if( prop ) {
scale = *prop->value.floatValue;
}
idVec3 worldPos = player->GetPhysics()->GetOrigin();
const sdPlayZone* playZone = GetPlayZone( window->GetUI(), worldPos );
if ( !playZone ) {
return false;
}
idVec2 size = playZone->GetSize() * scale;
idVec2 inverseSize;
inverseSize.x = 1.0f / size.x;
inverseSize.y = 1.0f / size.y;
idVec2 worldCamera;
ClampMapCamera( worldPos.ToVec2(), size, worldCamera, playZone->GetBounds() );
// Gordon: Draw Map out from camera
// [
idVec2 worldMins = playZone->GetBounds().GetMins();
idVec2 worldMaxs = playZone->GetBounds().GetMaxs();
idVec2 worldSpaceBounds = worldMaxs - worldMins;
WorldToMapTransform( inverseSize, worldMins, worldCamera, screenExtents );
WorldToMapTransform( inverseSize, worldMaxs, worldCamera, screenExtents );
// swap the y's as the transforms come out the other way about
Swap( worldMins.y, worldMaxs.y );
worldMaxs -= worldMins;
float radius = screenExtents.x * 0.5f;
idVec2 mapCenter( rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f );
bool fullSize = idMath::Fabs( scale - 1.0f ) < idMath::FLT_EPSILON;
// ]
idVec2 cursorPos( window->GetUI()->cursorPos );
sdCommandMapInfo* info;
for ( info = sdCommandMapInfoManager::GetInstance().GetIcons(); info; info = info->GetActiveNode().Next() ) {
const char* message = info->GetGuiMessage();
if ( !*message ) {
continue;
}
bool known = true;
idEntity* cmEntity = info->GetOwner();
if ( cmEntity ) {
known = cmEntity->SendCommandMapInfo( player );
if ( !known ) {
continue;
}
} else {
continue;
}
idVec2 coords;
info->GetOrigin( coords );
WorldToMapTransform( inverseSize, coords, worldCamera, screenExtents );
coords += screenPos;
if ( !fullSize ) {
idVec2 diff = coords - mapCenter;
if ( diff.LengthSqr() > radius ) {
continue;
}
}
// Gordon: FIXME: Info should handle this check
idVec2 halfSize = info->GetSize() * 0.5f;
if ( cursorPos.x < coords.x - halfSize.x || cursorPos.x > coords.x + halfSize.x ) {
continue;
}
if ( cursorPos.y < coords.y - halfSize.y || cursorPos.y > coords.y + halfSize.y ) {
continue;
}
sdGuiInterface* guiInterface = cmEntity->GetGuiInterface();
if ( !guiInterface ) {
gameLocal.Warning( "sdCommandMapPost::HandleLocalPlayerCommandMapInput Gui Message on Command Map Icon on Entity with no Gui Interface" );
continue;
}
if ( gameLocal.isClient ) {
sdReliableClientMessage msg( GAME_RELIABLE_CMESSAGE_GUISCRIPT );
msg.WriteBits( gameLocal.GetSpawnId( cmEntity ), 32 );
msg.WriteString( message );
msg.Send();
}
gameLocal.HandleGuiScriptMessage( player, cmEntity, message );
return true;
}
return false;
}
/*
============
sdCommandMapPost::DrawLocalPlayerCommandMapInfo
============
*/
void sdCommandMapPost::DrawLocalPlayerCommandMapInfo( sdUserInterfaceLocal* ui, float x, float y, float w, float h ) {
DrawLocalPlayerCommandMapInfo( ui, x, y, w, h, vec2_zero );
}
/*
============
sdCommandMapPost::GetPlayZone
============
*/
const sdPlayZone* sdCommandMapPost::GetPlayZone( sdUserInterfaceLocal* ui, const idVec3& worldPos ) {
int playzoneId = -1;
if ( sdProperties::sdProperty* prop = ui->GetState().GetProperty( "playZone", sdProperties::PT_FLOAT )) {
playzoneId = idMath::Ftoi( *prop->value.floatValue );
}
const sdPlayZone* zone = NULL;
if( playzoneId != -1 ) {
zone = gameLocal.GetChoosablePlayZone( playzoneId );
}
if( zone == NULL ) {
zone = gameLocal.GetPlayZone( worldPos, sdPlayZone::PZF_COMMANDMAP );
}
return zone;
}
/*
================
sdCommandMapPost::DrawLocalPlayerCommandMapInfo
================
*/
void sdCommandMapPost::DrawLocalPlayerCommandMapInfo( sdUserInterfaceLocal* ui, float x, float y, float w, float h, const idVec2& offset ) {
idPlayer* player = gameLocal.GetLocalViewPlayer();
if ( player == NULL && !gameLocal.serverIsRepeater ) {
return;
}
sdTeamInfo* team = player == NULL ? NULL : player->GetGameTeam();
idVec2 screenPos( x, y );
idVec2 screenExtents( w, h );
float scale = 1.f;
bool drawSquare = false;
// jrad - allow local overrides for vehicle cockpits, warroom maps, etc
sdProperties::sdProperty* prop = ui->GetState().GetProperty( "mapZoomLevel", sdProperties::PT_FLOAT );
if( !prop ) {
sdUserInterfaceScope* scope = gameLocal.globalProperties.GetSubScope( "gameHud" );
if( scope ) {
prop = scope->GetProperty( "mapZoomLevel", sdProperties::PT_FLOAT );
}
}
if( prop != NULL ) {
scale = *prop->value.floatValue;
}
bool fullSize = idMath::Fabs( scale - 1.0f ) < idMath::FLT_EPSILON;
if ( sdProperties::sdProperty* prop = ui->GetState().GetProperty( "drawSquare", sdProperties::PT_FLOAT )) {
drawSquare = *prop->value.floatValue == 1.0f;
}
if( drawSquare ) {
fullSize = true;
}
renderView_t repeaterView;
if ( gameLocal.serverIsRepeater ) {
gameLocal.playerView.CalculateRepeaterView( repeaterView );
}
idVec3 worldPos;
if ( gameLocal.serverIsRepeater ) {
worldPos = repeaterView.vieworg;
} else {
if ( player->GetRemoteCamera() != NULL ) {
worldPos = player->GetRenderView()->vieworg;
} else {
worldPos = player->GetPhysics()->GetOrigin();
}
}
const sdPlayZone* playZone = GetPlayZone( ui, worldPos );
if ( playZone == NULL ) {
return;
}
idVec2 size = playZone->GetSize() * scale;
idVec2 inverseSize;
inverseSize.x = 1.0f / size.x;
inverseSize.y = 1.0f / size.y;
idVec2 worldCamera;
ClampMapCamera( worldPos.ToVec2(), size, worldCamera, playZone->GetBounds() );
// Gordon: Draw Map out from camera
// [
idVec2 worldMins = playZone->GetBounds().GetMins();
idVec2 worldMaxs = playZone->GetBounds().GetMaxs();
idVec2 worldSpaceBounds = worldMaxs - worldMins;
float xOffset = ( ( worldCamera.x - worldMins.x ) / worldSpaceBounds.x );
float yOffset = -( ( worldCamera.y - worldMins.y ) / worldSpaceBounds.y );
float radius = screenExtents.x * 0.5f;
float rotAngle = 0.0f;
if( !fullSize ) {
if( sdCommandMapInfo::g_rotateCommandMap.GetBool() ) {
idPlayer* player = gameLocal.GetLocalPlayer();
if ( gameLocal.serverIsRepeater ) {
rotAngle = repeaterView.viewaxis.ToAngles().yaw - 90.0f;
} else if ( player != NULL ) {
idMat3 pAxis;
player->GetRenderViewAxis( pAxis );
rotAngle = pAxis.ToAngles().yaw - 90.0f;
}
}
}
const idMaterial* cmMaterial = playZone->GetCommandMapMaterial();
if ( fullSize && !drawSquare ) {
deviceContext->DrawMaterial( x, y, w, h, cmMaterial, colorWhite );
} else if( drawSquare ) {
deviceContext->DrawMaterial( x, y, w, h, cmMaterial, colorWhite, scale, scale, xOffset - 0.5f * scale, yOffset - 0.5f * scale );
} else {
idVec2 radii( w * 0.5f, h * 0.5f );
deviceContext->DrawCircleMaterial( x + radii.x, y + radii.y, radii, idWinding2D::MAX_POINTS, idVec4( xOffset, yOffset, 0.5f * scale, 0.5f * scale ), cmMaterial, colorWhite, rotAngle );
}
// ]
}
/*
================
sdCommandMapPost::DrawLocalPlayerCommandMapInfo_Icons
================
*/
void sdCommandMapPost::DrawLocalPlayerCommandMapInfo_Icons( sdUserInterfaceLocal* ui, float x, float y, float w, float h ) {
idPlayer* player = gameLocal.GetLocalViewPlayer();
if ( player == NULL && !gameLocal.serverIsRepeater ) {
return;
}
idVec2 screenPos( x, y );
idVec2 screenExtents( w, h );
float scale = 1.f;
bool drawSquare = false;
// jrad - allow local overrides for vehicle cockpits, warroom maps, etc
sdProperties::sdProperty* prop = ui->GetState().GetProperty( "mapZoomLevel", sdProperties::PT_FLOAT );
if( prop == NULL ) {
sdUserInterfaceScope* scope = gameLocal.globalProperties.GetSubScope( "gameHud" );
if( scope != NULL ) {
prop = scope->GetProperty( "mapZoomLevel", sdProperties::PT_FLOAT );
}
}
if( prop ) {
scale = *prop->value.floatValue;
}
bool fullSize = idMath::Fabs( scale - 1.0f ) < idMath::FLT_EPSILON;
if ( sdProperties::sdProperty* prop = ui->GetState().GetProperty( "drawSquare", sdProperties::PT_FLOAT )) {
drawSquare = *prop->value.floatValue == 1.0f;
}
if( drawSquare ) {
fullSize = true;
}
renderView_t repeaterView;
if ( gameLocal.serverIsRepeater ) {
gameLocal.playerView.CalculateRepeaterView( repeaterView );
}
idMat2 rotation( mat2_identity );
float rotAngle = 0.0f;
if( !fullSize) {
if( sdCommandMapInfo::g_rotateCommandMap.GetBool() ) {
idPlayer* player = gameLocal.GetLocalPlayer();
if ( gameLocal.serverIsRepeater ) {
rotAngle = repeaterView.viewaxis.ToAngles().yaw - 90.0f;
rotation.Rotation( DEG2RAD( rotAngle ) );
rotation.TransposeSelf();
} else if ( player != NULL ) {
idMat3 pAxis;
player->GetRenderViewAxis( pAxis );
rotAngle = pAxis.ToAngles().yaw - 90.0f;
rotation.Rotation( DEG2RAD( rotAngle ));
rotation.TransposeSelf();
}
}
}
idVec3 worldPos;
if ( gameLocal.serverIsRepeater ) {
worldPos = repeaterView.vieworg;
} else {
if ( player->GetRemoteCamera() != NULL ) {
worldPos = player->GetRenderView()->vieworg;
} else {
worldPos = player->GetPhysics()->GetOrigin();
}
}
const sdPlayZone* playZone = GetPlayZone( ui, worldPos );
if ( playZone == NULL ) {
return;
}
idVec2 size = playZone->GetSize() * scale;
idVec2 inverseSize;
inverseSize.x = 1.0f / size.x;
inverseSize.y = 1.0f / size.y;
idVec2 worldCamera;
ClampMapCamera( worldPos.ToVec2(), size, worldCamera, playZone->GetBounds() );
// Gordon: Draw Map out from camera
// [
idVec2 worldMins = playZone->GetBounds().GetMins();
idVec2 worldMaxs = playZone->GetBounds().GetMaxs();
idVec2 worldSpaceBounds = worldMaxs - worldMins;
idVec2 mapCamera = worldCamera;
WorldToMapTransform( inverseSize, worldMins, worldCamera, screenExtents );
WorldToMapTransform( inverseSize, worldMaxs, worldCamera, screenExtents );
WorldToMapTransform( inverseSize, mapCamera, worldCamera, screenExtents );
// swap the y's as the transforms come out the other way about
Swap( worldMins.y, worldMaxs.y );
worldMaxs -= worldMins;
idVec2 radius = screenExtents * 0.5f;
idVec2 center( w * 0.5f, h * 0.5f );
idVec2 mapCenter( x + center.x, y + center.y );
float sizeAdjustment = 1.0f;
if ( sdProperties::sdProperty* prop = ui->GetState().GetProperty( "iconScaleAdjustment", sdProperties::PT_FLOAT )) {
sizeAdjustment = *prop->value.floatValue;
}
sdCommandMapInfo* info;
for ( info = sdCommandMapInfoManager::GetInstance().GetIcons(); info; info = info->GetActiveNode().Next() ) {
bool known = true;
const sdRequirementContainer& requirements = info->GetRequirements();
if ( requirements.HasRequirements() ) {
if ( player == NULL ) {
continue;
}
if ( !requirements.Check( player, info->GetOwner() ) ) {
continue;
}
}
if ( info->OnlyInFullView() && scale < 1.0f ) {
continue;
}
if ( !info->IsAlwaysKnown() ) {
idEntity* cmEntity = info->GetOwner();
if ( cmEntity ) {
bool sameTeam = player->GetEntityAllegiance( cmEntity ) == TA_FRIEND;
bool enemyAlwaysKnown = info->EnemyAlwaysKnown();
if ( enemyAlwaysKnown ) {
if ( !sameTeam ) {
known = true;
} else {
known = cmEntity->IsInRadar( player );
}
} else {
known = cmEntity->SendCommandMapInfo( player );
}
if ( !known ) {
continue;
}
if ( known && !enemyAlwaysKnown ) {
known = info->EnemyOnly() ^ sameTeam;
}
}
}
idVec2 coords;
info->GetOrigin( coords );
WorldToMapTransform( inverseSize, coords, worldCamera, screenExtents );
if( coords.x < worldMins.x || coords.x > worldMaxs.x ) {
continue;
}
if( coords.y < worldMins.y || coords.y > worldMaxs.y ) {
continue;
}
coords -= center;
coords *= rotation;
coords += center;
coords += screenPos;
if ( !fullSize && !drawSquare ) {
idVec2 diff = coords - mapCenter;
float length = diff.Normalize();
if ( length >= radius.x || length >= radius.y ) {
if ( info->CanAdjustPosition() ) {
coords = idVec2( diff.x * radius.x, diff.y * radius.y );
coords += mapCenter;
known = false;
}
}
}
if ( !info->IsAlwaysKnown() ) {
if ( drawSquare && ( coords.x < x || coords.y < y || coords.x > x + w || coords.y > y + w ) ) {
continue;
}
}
for ( int i = 6; i < 12; i++ ) {
info->SetShaderParm( i, ui->GetShaderParms( i ) );
}
info->Draw( player, coords, screenPos, screenExtents, inverseSize, known, sizeAdjustment, rotation, rotAngle, fullSize );
}
}