Basic Summary: Issue 743: [Chat UI] Option to italicize actions (/me) in chat - Adds debug LiruItalicizeActions, and a checkbox to Adv. Chat->Chat UI preferences Issue 737: [Frosting] Annoyance Removal (Red beacon after teleport using LM's) - Adds debug ClearBeaconAfterTeleport, checkbox under System->General Issue 639: [Frosting] The agent isn't identified properly in chat - Oh what a silly issue this was, it's as though whoever wrote this didn't care. Fixes issue where names in logs do not match names in chat due to display name system Fixes the issue in which Unnamed objects got named by a hardcoded string under certain circumstances. Issue 813: [Frosting] When only accepting from friends, do not display incoming chat notification for nonfriends - Also broke the setting out, separating it from the voice calls friend only setting - Adds InstantMessagesFriendsOnly debug setting and checkbox in Adv. Chat->Chat/IM Issue 764: Copy SLURL from Map returns correct region but wrong coordinates. Satisfied the longstanding issue of inflexible autoresponse options. - Autoresponse now has its own tab in Adv. Chat preferences: Busy, Muted, nonfriends, and anyone (or just friends) can have separate responses, along with items of your choosing. - Prevent doubling up with the first repeated autoresponse due to typing message and normal message. Translator Summary: Adv. Chat->Chat UI->"Italicize action messages (/me)" System->General->"Clear red destination beacon after teleporting" Drop Targets for floater_ao.xml, panel_avatar.xml, panel_group_notices.xml, and panel_preferences_ascent_system.xml Adv. Chat->Chat/IM->"Only accept IMs from Friends" Please clean up the Busy Mode Response elements from panel_preferences_im.xml strings.xml now has "IM_autoresponse_minutes" Adv. Chat (panel_preferences_ascent_chat.xml) now has a new panel "Autoresponse", please clean up the old Autoresponse elements from Chat/IM tab and translate this panel. Developer Summary: Adds EChatStyle to LLChat, used for identifying what style a piece of chat is. Update settings_per_account.xml - Reorganized the ascent specific section. - Removes a few old and unused settings Better organize settings_per_account_ascent.xml - TODO: Actually get this include system working and remove the Ascent specific section in settings_per_account.xml Modernize LLDropTarget and make it more flexible and stand alone - The Text of drop targets is now a child of the target itself, meaning the necessity of having a static instance to the parent is eliminated - Drop targets are now one element in UI XML. - Drop targets now have fill_parent option which allows the target to spread over the parent, while the text, tool_tip, and border stays in place - If Drop Targets have a control_name, it is from the per account settings group, since Items must be in the inventory of the account in question. - All drop targets now use the common LLDropTarget class instead of their own. - LLGroupDropTarget is now derived from LLDropTarget and has its own tag group_drop_target. Cleaned up the focus functions we use to focus the input bar, setInputFocus exists for their purpose. Updated our llim* code to line up better with upstream and conform to styling. Polished LLTracker and LLFloaterWorldMap a bit Cleaned/Updated up LLStyleMap a bit. Optimized autoresponse code: - wildcards are now replaced via boost::algorithm::replace_all - Autoresponse and related chat enhancements are now performed inside their case, instead of by the large if block above.
846 lines
22 KiB
C++
846 lines
22 KiB
C++
/**
|
|
* @file lltracker.cpp
|
|
* @brief Container for objects user is tracking.
|
|
*
|
|
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2003-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
// library includes
|
|
#include "llcoord.h"
|
|
#include "lldarray.h"
|
|
#include "llfontgl.h"
|
|
#include "llgl.h"
|
|
#include "llrender.h"
|
|
#include "llinventory.h"
|
|
#include "llmemory.h"
|
|
#include "llstring.h"
|
|
#include "lluuid.h"
|
|
#include "v3math.h"
|
|
#include "v3dmath.h"
|
|
#include "v4color.h"
|
|
|
|
// viewer includes
|
|
#include "llappviewer.h"
|
|
#include "lltracker.h"
|
|
#include "llagent.h"
|
|
#include "llagentcamera.h"
|
|
#include "llcallingcard.h"
|
|
#include "llcolorscheme.h"
|
|
#include "llfloaterworldmap.h"
|
|
#include "llhudtext.h"
|
|
#include "llhudview.h"
|
|
#include "llinventorydefines.h"
|
|
#include "llinventoryobserver.h"
|
|
#include "lllandmarklist.h"
|
|
#include "llprogressview.h"
|
|
#include "llsky.h"
|
|
#include "llui.h"
|
|
#include "llviewercamera.h"
|
|
#include "llviewerinventory.h"
|
|
#include "llviewerwindow.h"
|
|
#include "llworld.h"
|
|
#include "llworldmapview.h"
|
|
#include "llviewercontrol.h"
|
|
|
|
// [RLVa:KB]
|
|
#include "rlvhandler.h"
|
|
// [/RLVa:KB]
|
|
|
|
const F32 DESTINATION_REACHED_RADIUS = 3.0f;
|
|
const F32 DESTINATION_VISITED_RADIUS = 6.0f;
|
|
|
|
// this last one is useful for when the landmark is
|
|
// very close to agent when tracking is turned on
|
|
const F32 DESTINATION_UNVISITED_RADIUS = 12.0f;
|
|
|
|
const S32 ARROW_OFF_RADIUS_SQRD = 100;
|
|
|
|
const S32 HUD_ARROW_SIZE = 32;
|
|
|
|
// static
|
|
LLTracker *LLTracker::sTrackerp = NULL;
|
|
BOOL LLTracker::sCheesyBeacon = FALSE;
|
|
|
|
LLTracker::LLTracker()
|
|
: mTrackingStatus(TRACKING_NOTHING),
|
|
mTrackingLocationType(LOCATION_NOTHING),
|
|
mHUDArrowCenterX(0),
|
|
mHUDArrowCenterY(0),
|
|
mToolTip( "" ),
|
|
mTrackedLandmarkName(""),
|
|
mHasReachedLandmark(FALSE),
|
|
mHasLandmarkPosition(FALSE),
|
|
mLandmarkHasBeenVisited(FALSE),
|
|
mTrackedLocationName( "" ),
|
|
mIsTrackingLocation(FALSE),
|
|
mHasReachedLocation(FALSE)
|
|
{ }
|
|
|
|
|
|
LLTracker::~LLTracker()
|
|
{
|
|
purgeBeaconText();
|
|
}
|
|
|
|
|
|
// static
|
|
void LLTracker::stopTracking(bool clear_ui)
|
|
{
|
|
instance()->stopTrackingAll(clear_ui);
|
|
}
|
|
|
|
|
|
// static virtual
|
|
void LLTracker::drawHUDArrow()
|
|
{
|
|
if (gViewerWindow->getProgressView()->getVisible()) return;
|
|
/* tracking autopilot destination has been disabled
|
|
-- 2004.01.09, Leviathan
|
|
// Draw dot for autopilot target
|
|
if (gAgent.getAutoPilot())
|
|
{
|
|
instance()->drawMarker( gAgent.getAutoPilotTargetGlobal(), gTrackColor );
|
|
return;
|
|
}
|
|
*/
|
|
switch (getTrackingStatus())
|
|
{
|
|
case TRACKING_AVATAR:
|
|
// Tracked avatar
|
|
if(LLAvatarTracker::instance().haveTrackingInfo())
|
|
{
|
|
instance()->drawMarker( LLAvatarTracker::instance().getGlobalPos(), gTrackColor );
|
|
}
|
|
break;
|
|
|
|
case TRACKING_LANDMARK:
|
|
instance()->drawMarker( getTrackedPositionGlobal(), gTrackColor );
|
|
break;
|
|
|
|
case TRACKING_LOCATION:
|
|
// HACK -- try to keep the location just above the terrain
|
|
#if 0
|
|
// UNHACKED by CRO - keep location where the location is
|
|
instance()->mTrackedPositionGlobal.mdV[VZ] =
|
|
0.9f * instance()->mTrackedPositionGlobal.mdV[VZ]
|
|
+ 0.1f * (LLWorld::getInstance()->resolveLandHeightGlobal(getTrackedPositionGlobal()) + 1.5f);
|
|
#endif
|
|
instance()->mTrackedPositionGlobal.mdV[VZ] = llclamp((F32)instance()->mTrackedPositionGlobal.mdV[VZ], LLWorld::getInstance()->resolveLandHeightGlobal(getTrackedPositionGlobal()) + 1.5f, (F32)instance()->getTrackedPositionGlobal().mdV[VZ]);
|
|
instance()->drawMarker( getTrackedPositionGlobal(), gTrackColor );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// static
|
|
void LLTracker::render3D()
|
|
{
|
|
if (!gFloaterWorldMap)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Arbitary location beacon
|
|
if( instance()->mIsTrackingLocation )
|
|
{
|
|
if (!instance()->mBeaconText)
|
|
{
|
|
instance()->mBeaconText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
|
|
instance()->mBeaconText->setDoFade(FALSE);
|
|
}
|
|
|
|
LLVector3d pos_global = instance()->mTrackedPositionGlobal;
|
|
// (z-attenuation < 1) means compute "shorter" distance in z-axis,
|
|
// so cancel tracking even if avatar is a little above or below.
|
|
F32 dist = gFloaterWorldMap->getDistanceToDestination(pos_global, 0.5f);
|
|
if (dist < DESTINATION_REACHED_RADIUS)
|
|
{
|
|
instance()->stopTrackingLocation();
|
|
}
|
|
else
|
|
{
|
|
//renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor,
|
|
// instance()->mBeaconText, instance()->mTrackedLocationName );
|
|
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
|
|
renderBeacon(instance()->mTrackedPositionGlobal, gTrackColor, instance()->mBeaconText,
|
|
(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? instance()->mTrackedLocationName : RlvStrings::getString(RLV_STRING_HIDDEN));
|
|
// [/RLVa:KB]
|
|
}
|
|
}
|
|
|
|
// Landmark beacon
|
|
else if( !instance()->mTrackedLandmarkAssetID.isNull() )
|
|
{
|
|
if (!instance()->mBeaconText)
|
|
{
|
|
instance()->mBeaconText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
|
|
instance()->mBeaconText->setDoFade(FALSE);
|
|
}
|
|
|
|
if (instance()->mHasLandmarkPosition)
|
|
{
|
|
F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->mTrackedPositionGlobal, 1.0f);
|
|
|
|
if ( !instance()->mLandmarkHasBeenVisited
|
|
&& dist < DESTINATION_VISITED_RADIUS )
|
|
{
|
|
// its close enough ==> flag as visited
|
|
instance()->setLandmarkVisited();
|
|
}
|
|
|
|
if ( !instance()->mHasReachedLandmark
|
|
&& dist < DESTINATION_REACHED_RADIUS )
|
|
{
|
|
// its VERY CLOSE ==> automatically stop tracking
|
|
instance()->stopTrackingLandmark();
|
|
}
|
|
else
|
|
{
|
|
if ( instance()->mHasReachedLandmark
|
|
&& dist > DESTINATION_UNVISITED_RADIUS )
|
|
{
|
|
// this is so that landmark beacons don't immediately
|
|
// disappear when they're created only a few meters
|
|
// away, yet disappear when the agent wanders away
|
|
// and back again
|
|
instance()->mHasReachedLandmark = FALSE;
|
|
}
|
|
//renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor,
|
|
// instance()->mBeaconText, instance()->mTrackedLandmarkName );
|
|
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
|
|
renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor, instance()->mBeaconText,
|
|
(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? instance()->mTrackedLandmarkName
|
|
: RlvStrings::getString(RLV_STRING_HIDDEN));
|
|
// [/RLVa:KB]
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// probably just finished downloading the asset
|
|
instance()->cacheLandmarkPosition();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Avatar beacon
|
|
LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
|
|
if(av_tracker.haveTrackingInfo())
|
|
{
|
|
if (!instance()->mBeaconText)
|
|
{
|
|
instance()->mBeaconText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
|
|
instance()->mBeaconText->setDoFade(FALSE);
|
|
}
|
|
|
|
F32 dist = gFloaterWorldMap->getDistanceToDestination(instance()->getTrackedPositionGlobal(), 0.0f);
|
|
if (dist < DESTINATION_REACHED_RADIUS)
|
|
{
|
|
instance()->stopTrackingAvatar();
|
|
}
|
|
else
|
|
{
|
|
//renderBeacon( av_tracker.getGlobalPos(), gTrackColor,
|
|
// instance()->mBeaconText, av_tracker.getName() );
|
|
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
|
|
renderBeacon( av_tracker.getGlobalPos(), gTrackColor, instance()->mBeaconText,
|
|
(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? av_tracker.getName() : RlvStrings::getString(RLV_STRING_HIDDEN));
|
|
// [/RLVa:KB]
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOL stop_tracking = FALSE;
|
|
const LLUUID& avatar_id = av_tracker.getAvatarID();
|
|
if(avatar_id.isNull())
|
|
{
|
|
stop_tracking = TRUE;
|
|
}
|
|
else
|
|
{
|
|
const LLRelationship* buddy = av_tracker.getBuddyInfo(avatar_id);
|
|
if(buddy && !buddy->isOnline() && !gAgent.isGodlike())
|
|
{
|
|
stop_tracking = TRUE;
|
|
}
|
|
if(!buddy && !gAgent.isGodlike())
|
|
{
|
|
stop_tracking = TRUE;
|
|
}
|
|
}
|
|
if(stop_tracking)
|
|
{
|
|
instance()->stopTrackingAvatar();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// static
|
|
void LLTracker::trackAvatar( const LLUUID& avatar_id, const std::string& name )
|
|
{
|
|
instance()->stopTrackingLandmark();
|
|
instance()->stopTrackingLocation();
|
|
|
|
LLAvatarTracker::instance().track( avatar_id, name );
|
|
instance()->mTrackingStatus = TRACKING_AVATAR;
|
|
instance()->mLabel = name;
|
|
instance()->mToolTip = "";
|
|
}
|
|
|
|
|
|
// static
|
|
void LLTracker::trackLandmark( const LLUUID& asset_id, const LLUUID& item_id, const std::string& name)
|
|
{
|
|
instance()->stopTrackingAvatar();
|
|
instance()->stopTrackingLocation();
|
|
|
|
instance()->mTrackedLandmarkAssetID = asset_id;
|
|
instance()->mTrackedLandmarkItemID = item_id;
|
|
instance()->mTrackedLandmarkName = name;
|
|
instance()->cacheLandmarkPosition();
|
|
instance()->mTrackingStatus = TRACKING_LANDMARK;
|
|
instance()->mLabel = name;
|
|
instance()->mToolTip = "";
|
|
}
|
|
|
|
|
|
// static
|
|
void LLTracker::trackLocation(const LLVector3d& pos_global, const std::string& full_name, const std::string& tooltip, ETrackingLocationType location_type)
|
|
{
|
|
instance()->stopTrackingAvatar();
|
|
instance()->stopTrackingLandmark();
|
|
|
|
instance()->mTrackedPositionGlobal = pos_global;
|
|
instance()->mTrackedLocationName = full_name;
|
|
instance()->mIsTrackingLocation = TRUE;
|
|
instance()->mTrackingStatus = TRACKING_LOCATION;
|
|
instance()->mTrackingLocationType = location_type;
|
|
instance()->mLabel = full_name;
|
|
instance()->mToolTip = tooltip;
|
|
}
|
|
|
|
|
|
// static
|
|
BOOL LLTracker::handleMouseDown(S32 x, S32 y)
|
|
{
|
|
BOOL eat_mouse_click = FALSE;
|
|
// fortunately, we can always compute the tracking arrow center
|
|
S32 dist_sqrd = (x - instance()->mHUDArrowCenterX) * (x - instance()->mHUDArrowCenterX) +
|
|
(y - instance()->mHUDArrowCenterY) * (y - instance()->mHUDArrowCenterY);
|
|
if (dist_sqrd < ARROW_OFF_RADIUS_SQRD)
|
|
{
|
|
/* tracking autopilot destination has been disabled
|
|
-- 2004.01.09, Leviathan
|
|
// turn off tracking
|
|
if (gAgent.getAutoPilot())
|
|
{
|
|
gAgent.stopAutoPilot(TRUE); // TRUE because cancelled by user
|
|
eat_mouse_click = TRUE;
|
|
}
|
|
*/
|
|
if (getTrackingStatus())
|
|
{
|
|
instance()->stopTrackingAll();
|
|
eat_mouse_click = TRUE;
|
|
}
|
|
}
|
|
return eat_mouse_click;
|
|
}
|
|
|
|
|
|
// static
|
|
LLVector3d LLTracker::getTrackedPositionGlobal()
|
|
{
|
|
LLVector3d pos_global;
|
|
switch (getTrackingStatus())
|
|
{
|
|
case TRACKING_AVATAR:
|
|
{
|
|
LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
|
|
if (av_tracker.haveTrackingInfo())
|
|
{
|
|
pos_global = av_tracker.getGlobalPos(); }
|
|
break;
|
|
}
|
|
case TRACKING_LANDMARK:
|
|
if( instance()->mHasLandmarkPosition )
|
|
{
|
|
pos_global = instance()->mTrackedPositionGlobal;
|
|
}
|
|
break;
|
|
case TRACKING_LOCATION:
|
|
pos_global = instance()->mTrackedPositionGlobal;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return pos_global;
|
|
}
|
|
|
|
|
|
// static
|
|
BOOL LLTracker::hasLandmarkPosition()
|
|
{
|
|
if (!instance()->mHasLandmarkPosition)
|
|
{
|
|
// maybe we just received the landmark position info
|
|
instance()->cacheLandmarkPosition();
|
|
}
|
|
return instance()->mHasLandmarkPosition;
|
|
}
|
|
|
|
|
|
// static
|
|
const std::string& LLTracker::getTrackedLocationName()
|
|
{
|
|
return instance()->mTrackedLocationName;
|
|
}
|
|
|
|
F32 pulse_func(F32 t, F32 z)
|
|
{
|
|
if (!LLTracker::sCheesyBeacon)
|
|
{
|
|
return 0.f;
|
|
}
|
|
|
|
t *= F_PI;
|
|
z -= t*64.f - 256.f;
|
|
|
|
F32 a = cosf(z*F_PI/512.f)*10.0f;
|
|
a = llmax(a, 9.9f);
|
|
a -= 9.9f;
|
|
a *= 10.f;
|
|
return a;
|
|
}
|
|
|
|
void draw_shockwave(F32 center_z, F32 t, S32 steps, LLColor4 color)
|
|
{
|
|
if (!LLTracker::sCheesyBeacon)
|
|
{
|
|
return;
|
|
}
|
|
|
|
t *= 0.6284f/F_PI;
|
|
|
|
t -= (F32) (S32) t;
|
|
|
|
t = llmax(t, 0.5f);
|
|
t -= 0.5f;
|
|
t *= 2.0f;
|
|
|
|
F32 radius = t*16536.f;
|
|
|
|
// Inexact, but reasonably fast.
|
|
F32 delta = F_TWO_PI / steps;
|
|
F32 sin_delta = sin( delta );
|
|
F32 cos_delta = cos( delta );
|
|
F32 x = radius;
|
|
F32 y = 0.f;
|
|
|
|
LLColor4 ccol = LLColor4(1,1,1,(1.f-t)*0.25f);
|
|
gGL.begin(LLRender::TRIANGLE_FAN);
|
|
gGL.color4fv(ccol.mV);
|
|
gGL.vertex3f(0.f, 0.f, center_z);
|
|
// make sure circle is complete
|
|
steps += 1;
|
|
|
|
color.mV[3] = (1.f-t*t);
|
|
|
|
gGL.color4fv(color.mV);
|
|
while( steps-- )
|
|
{
|
|
// Successive rotations
|
|
gGL.vertex3f( x, y, center_z );
|
|
F32 x_new = x * cos_delta - y * sin_delta;
|
|
y = x * sin_delta + y * cos_delta;
|
|
x = x_new;
|
|
}
|
|
gGL.end();
|
|
}
|
|
|
|
|
|
// static
|
|
void LLTracker::renderBeacon(LLVector3d pos_global,
|
|
const LLColor4& color,
|
|
LLHUDText* hud_textp,
|
|
const std::string& label )
|
|
{
|
|
sCheesyBeacon = gSavedSettings.getBOOL("CheesyBeacon");
|
|
LLVector3d to_vec = pos_global - gAgentCamera.getCameraPositionGlobal();
|
|
|
|
F32 dist = (F32)to_vec.magVec();
|
|
F32 color_frac = 1.f;
|
|
if (dist > 0.99f * LLViewerCamera::getInstance()->getFar())
|
|
{
|
|
color_frac = 0.4f;
|
|
// pos_global = gAgentCamera.getCameraPositionGlobal() + 0.99f*(LLViewerCamera::getInstance()->getFar()/dist)*to_vec;
|
|
}
|
|
else
|
|
{
|
|
color_frac = 1.f - 0.6f*(dist/LLViewerCamera::getInstance()->getFar());
|
|
}
|
|
|
|
LLColor4 fogged_color = color_frac * color + (1 - color_frac)*gSky.getFogColor();
|
|
|
|
F32 FADE_DIST = 3.f;
|
|
fogged_color.mV[3] = llmax(0.2f, llmin(0.5f,(dist-FADE_DIST)/FADE_DIST));
|
|
|
|
LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(pos_global);
|
|
|
|
LLGLSTracker gls_tracker; // default+ CULL_FACE + LIGHTING + GL_BLEND + GL_ALPHA_TEST
|
|
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
|
LLGLDisable cull_face(GL_CULL_FACE);
|
|
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
|
|
|
|
|
|
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
|
gGL.pushMatrix();
|
|
{
|
|
gGL.translatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
|
|
|
|
draw_shockwave(1024.f, gRenderStartTime.getElapsedTimeF32(), 32, fogged_color);
|
|
|
|
gGL.color4fv(fogged_color.mV);
|
|
const U32 BEACON_VERTS = 256;
|
|
const F32 step = 1024.0f/BEACON_VERTS;
|
|
|
|
LLVector3 x_axis = LLViewerCamera::getInstance()->getLeftAxis();
|
|
F32 t = gRenderStartTime.getElapsedTimeF32();
|
|
F32 dr = dist/LLViewerCamera::getInstance()->getFar();
|
|
|
|
for (U32 i = 0; i < BEACON_VERTS; i++)
|
|
{
|
|
F32 x = x_axis.mV[0];
|
|
F32 y = x_axis.mV[1];
|
|
|
|
F32 z = i * step;
|
|
F32 z_next = (i+1)*step;
|
|
|
|
F32 a = pulse_func(t, z);
|
|
F32 an = pulse_func(t, z_next);
|
|
|
|
LLColor4 c_col = fogged_color + LLColor4(a,a,a,a);
|
|
LLColor4 col_next = fogged_color + LLColor4(an,an,an,an);
|
|
LLColor4 col_edge = fogged_color * LLColor4(a,a,a,0.0f);
|
|
LLColor4 col_edge_next = fogged_color * LLColor4(an,an,an,0.0f);
|
|
|
|
a *= 2.f;
|
|
a += 1.0f+dr;
|
|
|
|
an *= 2.f;
|
|
an += 1.0f+dr;
|
|
|
|
gGL.begin(LLRender::TRIANGLE_STRIP);
|
|
gGL.color4fv(col_edge.mV);
|
|
gGL.vertex3f(-x*a, -y*a, z);
|
|
gGL.color4fv(col_edge_next.mV);
|
|
gGL.vertex3f(-x*an, -y*an, z_next);
|
|
|
|
gGL.color4fv(c_col.mV);
|
|
gGL.vertex3f(0, 0, z);
|
|
gGL.color4fv(col_next.mV);
|
|
gGL.vertex3f(0, 0, z_next);
|
|
|
|
gGL.color4fv(col_edge.mV);
|
|
gGL.vertex3f(x*a,y*a,z);
|
|
gGL.color4fv(col_edge_next.mV);
|
|
gGL.vertex3f(x*an,y*an,z_next);
|
|
|
|
gGL.end();
|
|
}
|
|
}
|
|
gGL.popMatrix();
|
|
|
|
std::string text;
|
|
text = llformat( "%.0f m", to_vec.magVec());
|
|
|
|
std::string str;
|
|
str += label;
|
|
str += '\n';
|
|
str += text;
|
|
|
|
hud_textp->setFont(LLFontGL::getFontSansSerif());
|
|
hud_textp->setZCompare(FALSE);
|
|
hud_textp->setColor(LLColor4(1.f, 1.f, 1.f, llmax(0.2f, llmin(1.f,(dist-FADE_DIST)/FADE_DIST))));
|
|
|
|
hud_textp->setString(str);
|
|
hud_textp->setVertAlignment(LLHUDText::ALIGN_VERT_CENTER);
|
|
hud_textp->setPositionAgent(pos_agent);
|
|
}
|
|
|
|
|
|
void LLTracker::stopTrackingAll(BOOL clear_ui)
|
|
{
|
|
switch (mTrackingStatus)
|
|
{
|
|
case TRACKING_AVATAR :
|
|
stopTrackingAvatar(clear_ui);
|
|
break;
|
|
case TRACKING_LANDMARK :
|
|
stopTrackingLandmark(clear_ui);
|
|
break;
|
|
case TRACKING_LOCATION :
|
|
stopTrackingLocation(clear_ui);
|
|
break;
|
|
default:
|
|
mTrackingStatus = TRACKING_NOTHING;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void LLTracker::stopTrackingAvatar(BOOL clear_ui)
|
|
{
|
|
LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
|
|
if( !av_tracker.getAvatarID().isNull() )
|
|
{
|
|
av_tracker.untrack( av_tracker.getAvatarID() );
|
|
}
|
|
|
|
purgeBeaconText();
|
|
gFloaterWorldMap->clearAvatarSelection(clear_ui);
|
|
mTrackingStatus = TRACKING_NOTHING;
|
|
}
|
|
|
|
|
|
void LLTracker::stopTrackingLandmark(BOOL clear_ui)
|
|
{
|
|
purgeBeaconText();
|
|
mTrackedLandmarkAssetID.setNull();
|
|
mTrackedLandmarkItemID.setNull();
|
|
mTrackedLandmarkName.assign("");
|
|
mTrackedPositionGlobal.zeroVec();
|
|
mHasLandmarkPosition = FALSE;
|
|
mHasReachedLandmark = FALSE;
|
|
mLandmarkHasBeenVisited = TRUE;
|
|
gFloaterWorldMap->clearLandmarkSelection(clear_ui);
|
|
mTrackingStatus = TRACKING_NOTHING;
|
|
}
|
|
|
|
|
|
void LLTracker::stopTrackingLocation(BOOL clear_ui)
|
|
{
|
|
purgeBeaconText();
|
|
mTrackedLocationName.assign("");
|
|
mIsTrackingLocation = FALSE;
|
|
mTrackedPositionGlobal.zeroVec();
|
|
gFloaterWorldMap->clearLocationSelection(clear_ui);
|
|
mTrackingStatus = TRACKING_NOTHING;
|
|
mTrackingLocationType = LOCATION_NOTHING;
|
|
}
|
|
|
|
void LLTracker::clearFocus()
|
|
{
|
|
instance()->mTrackingStatus = TRACKING_NOTHING;
|
|
}
|
|
|
|
void LLTracker::drawMarker(const LLVector3d& pos_global, const LLColor4& color)
|
|
{
|
|
// get position
|
|
LLVector3 pos_local = gAgent.getPosAgentFromGlobal(pos_global);
|
|
|
|
// check in frustum
|
|
LLCoordGL screen;
|
|
S32 x = 0;
|
|
S32 y = 0;
|
|
const BOOL CLAMP = TRUE;
|
|
|
|
if (LLViewerCamera::getInstance()->projectPosAgentToScreen(pos_local, screen, CLAMP)
|
|
|| LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(pos_local, screen) )
|
|
{
|
|
gHUDView->screenPointToLocal(screen.mX, screen.mY, &x, &y);
|
|
|
|
// the center of the rendered position of the arrow obeys
|
|
// the following rules:
|
|
// (1) it lies on an ellipse centered on the target position
|
|
// (2) it lies on the line between the target and the window center
|
|
// (3) right now the radii of the ellipse are fixed, but eventually
|
|
// they will be a function of the target text
|
|
//
|
|
// from those rules we can compute the position of the
|
|
// lower left corner of the image
|
|
LLRect rect = gHUDView->getRect();
|
|
S32 x_center = lltrunc(0.5f * (F32)rect.getWidth());
|
|
S32 y_center = lltrunc(0.5f * (F32)rect.getHeight());
|
|
x = x - x_center; // x and y relative to center
|
|
y = y - y_center;
|
|
F32 dist = sqrt((F32)(x*x + y*y));
|
|
S32 half_arrow_size = lltrunc(0.5f * HUD_ARROW_SIZE);
|
|
if (dist > 0.f)
|
|
{
|
|
const F32 ARROW_ELLIPSE_RADIUS_X = 2 * HUD_ARROW_SIZE;
|
|
const F32 ARROW_ELLIPSE_RADIUS_Y = HUD_ARROW_SIZE;
|
|
|
|
// compute where the arrow should be
|
|
F32 x_target = (F32)(x + x_center) - (ARROW_ELLIPSE_RADIUS_X * ((F32)x / dist) );
|
|
F32 y_target = (F32)(y + y_center) - (ARROW_ELLIPSE_RADIUS_Y * ((F32)y / dist) );
|
|
|
|
// keep the arrow within the window
|
|
F32 x_clamped = llclamp( x_target, (F32)half_arrow_size, (F32)(rect.getWidth() - half_arrow_size));
|
|
F32 y_clamped = llclamp( y_target, (F32)half_arrow_size, (F32)(rect.getHeight() - half_arrow_size));
|
|
|
|
F32 slope = (F32)(y) / (F32)(x);
|
|
F32 window_ratio = (F32)(rect.getHeight() - HUD_ARROW_SIZE) / (F32)(rect.getWidth() - HUD_ARROW_SIZE);
|
|
|
|
// if the arrow has been clamped on one axis
|
|
// then we need to compute the other axis
|
|
if (llabs(slope) > window_ratio)
|
|
{
|
|
if (y_clamped != (F32)y_target)
|
|
{
|
|
// clamp by y
|
|
x_clamped = (y_clamped - (F32)y_center) / slope + (F32)x_center;
|
|
}
|
|
}
|
|
else if (x_clamped != (F32)x_target)
|
|
{
|
|
// clamp by x
|
|
y_clamped = (x_clamped - (F32)x_center) * slope + (F32)y_center;
|
|
}
|
|
mHUDArrowCenterX = lltrunc(x_clamped);
|
|
mHUDArrowCenterY = lltrunc(y_clamped);
|
|
}
|
|
else
|
|
{
|
|
// recycle the old values
|
|
x = mHUDArrowCenterX - x_center;
|
|
y = mHUDArrowCenterY - y_center;
|
|
}
|
|
|
|
F32 angle = atan2( (F32)y, (F32)x );
|
|
|
|
gl_draw_scaled_rotated_image(mHUDArrowCenterX - half_arrow_size,
|
|
mHUDArrowCenterY - half_arrow_size,
|
|
HUD_ARROW_SIZE, HUD_ARROW_SIZE,
|
|
RAD_TO_DEG * angle,
|
|
LLWorldMapView::sTrackArrowImage->getImage(),
|
|
color);
|
|
}
|
|
}
|
|
|
|
|
|
void LLTracker::setLandmarkVisited()
|
|
{
|
|
// poke the inventory item
|
|
if (!mTrackedLandmarkItemID.isNull())
|
|
{
|
|
LLInventoryItem* i = gInventory.getItem( mTrackedLandmarkItemID );
|
|
LLViewerInventoryItem* item = (LLViewerInventoryItem*)i;
|
|
if ( item
|
|
&& !(item->getFlags()&LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED))
|
|
{
|
|
U32 flags = item->getFlags();
|
|
flags |= LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED;
|
|
item->setFlags(flags);
|
|
LLMessageSystem* msg = gMessageSystem;
|
|
msg->newMessage("ChangeInventoryItemFlags");
|
|
msg->nextBlock("AgentData");
|
|
msg->addUUID("AgentID", gAgent.getID());
|
|
msg->addUUID("SessionID", gAgent.getSessionID());
|
|
msg->nextBlock("InventoryData");
|
|
msg->addUUID("ItemID", mTrackedLandmarkItemID);
|
|
msg->addU32("Flags", flags);
|
|
gAgent.sendReliableMessage();
|
|
|
|
LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0);
|
|
gInventory.accountForUpdate(up);
|
|
|
|
// need to communicate that the icon needs to change...
|
|
gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item->getUUID());
|
|
gInventory.notifyObservers();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void LLTracker::cacheLandmarkPosition()
|
|
{
|
|
// the landmark asset download may have finished, in which case
|
|
// we'll now be able to figure out where we're trying to go
|
|
BOOL found_landmark = FALSE;
|
|
if( mTrackedLandmarkAssetID == LLFloaterWorldMap::getHomeID())
|
|
{
|
|
LLVector3d pos_global;
|
|
if ( gAgent.getHomePosGlobal( &mTrackedPositionGlobal ))
|
|
{
|
|
found_landmark = TRUE;
|
|
}
|
|
else
|
|
{
|
|
llwarns << "LLTracker couldn't find home pos" << llendl;
|
|
mTrackedLandmarkAssetID.setNull();
|
|
mTrackedLandmarkItemID.setNull();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LLLandmark* landmark = gLandmarkList.getAsset(mTrackedLandmarkAssetID);
|
|
if(landmark && landmark->getGlobalPos(mTrackedPositionGlobal))
|
|
{
|
|
found_landmark = TRUE;
|
|
|
|
// cache the object's visitation status
|
|
mLandmarkHasBeenVisited = FALSE;
|
|
LLInventoryItem* item = gInventory.getItem(mTrackedLandmarkItemID);
|
|
if ( item
|
|
&& item->getFlags()&LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED)
|
|
{
|
|
mLandmarkHasBeenVisited = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if ( found_landmark && gFloaterWorldMap )
|
|
{
|
|
mHasReachedLandmark = FALSE;
|
|
F32 dist = gFloaterWorldMap->getDistanceToDestination(mTrackedPositionGlobal, 1.0f);
|
|
if ( dist < DESTINATION_UNVISITED_RADIUS )
|
|
{
|
|
mHasReachedLandmark = TRUE;
|
|
}
|
|
mHasLandmarkPosition = TRUE;
|
|
}
|
|
mHasLandmarkPosition = found_landmark;
|
|
}
|
|
|
|
|
|
void LLTracker::purgeBeaconText()
|
|
{
|
|
if(!mBeaconText.isNull())
|
|
{
|
|
mBeaconText->markDead();
|
|
mBeaconText = NULL;
|
|
}
|
|
}
|
|
|