PageRenderTime 38ms CodeModel.GetById 18ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llteleporthistory.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 236 lines | 147 code | 33 blank | 56 comment | 25 complexity | 2e2a717283d4b444dbdc75e5ed9e5195 MD5 | raw file
  1/** 
  2 * @file llteleporthistory.cpp
  3 * @brief Teleport history
  4 *
  5 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llteleporthistory.h"
 30
 31#include "llparcel.h"
 32#include "llsdserialize.h"
 33
 34#include "llagent.h"
 35#include "llvoavatarself.h"
 36#include "llslurl.h"
 37#include "llviewercontrol.h"        // for gSavedSettings
 38#include "llviewerparcelmgr.h"
 39#include "llviewerregion.h"
 40#include "llworldmap.h"
 41#include "llagentui.h"
 42
 43//////////////////////////////////////////////////////////////////////////////
 44// LLTeleportHistoryItem
 45//////////////////////////////////////////////////////////////////////////////
 46
 47const std::string& LLTeleportHistoryItem::getTitle() const
 48{
 49	return gSavedSettings.getBOOL("NavBarShowCoordinates") ? mFullTitle : mTitle;
 50}
 51
 52//////////////////////////////////////////////////////////////////////////////
 53// LLTeleportHistory
 54//////////////////////////////////////////////////////////////////////////////
 55
 56LLTeleportHistory::LLTeleportHistory():
 57	mCurrentItem(-1),
 58	mRequestedItem(-1),
 59	mGotInitialUpdate(false),
 60	mTeleportHistoryStorage(NULL)
 61{
 62	mTeleportFinishedConn = LLViewerParcelMgr::getInstance()->
 63		setTeleportFinishedCallback(boost::bind(&LLTeleportHistory::updateCurrentLocation, this, _1));
 64	mTeleportFailedConn = LLViewerParcelMgr::getInstance()->
 65		setTeleportFailedCallback(boost::bind(&LLTeleportHistory::onTeleportFailed, this));
 66}
 67
 68LLTeleportHistory::~LLTeleportHistory()
 69{
 70	mTeleportFinishedConn.disconnect();
 71	mTeleportFailedConn.disconnect();
 72}
 73
 74void LLTeleportHistory::goToItem(int idx)
 75
 76{
 77	// Validate specified index.
 78	if (idx < 0 || idx >= (int)mItems.size())
 79	{
 80		llwarns << "Invalid teleport history index (" << idx << ") specified" << llendl;
 81		dump();
 82		return;
 83	}
 84	
 85	if (idx == mCurrentItem)
 86	{
 87		llwarns << "Will not teleport to the same location." << llendl;
 88		dump();
 89		return;
 90	}
 91
 92	// Attempt to teleport to the requested item.
 93	gAgent.teleportViaLocation(mItems[idx].mGlobalPos);
 94	mRequestedItem = idx;
 95}
 96
 97void LLTeleportHistory::onTeleportFailed()
 98{
 99	// Are we trying to teleport within the history?
100	if (mRequestedItem != -1)
101	{
102		// Not anymore.
103		mRequestedItem = -1;
104	}
105}
106
107void LLTeleportHistory::handleLoginComplete()
108{
109	if( mGotInitialUpdate )
110	{
111		return;
112	}
113	updateCurrentLocation(gAgent.getPositionGlobal());
114}
115
116
117void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
118{
119	if (!mTeleportHistoryStorage)
120	{
121		mTeleportHistoryStorage = LLTeleportHistoryStorage::getInstance();
122	}
123	if (mRequestedItem != -1) // teleport within the history in progress?
124	{
125		mCurrentItem = mRequestedItem;
126		mRequestedItem = -1;
127	}
128	else
129	{
130		//EXT-7034
131		//skip initial update if agent avatar is no valid yet
132		//this may happen when updateCurrentLocation called while login process
133		//sometimes isAgentAvatarValid return false and in this case new_pos
134		//(which actually is gAgent.getPositionGlobal() ) is invalid
135		//if this position will be saved then teleport back will teleport user to wrong position
136		if ( !mGotInitialUpdate && !isAgentAvatarValid() )
137		{
138			return ;
139		}
140
141		// If we're getting the initial location update
142		// while we already have a (loaded) non-empty history,
143		// there's no need to purge forward items or add a new item.
144
145		if (mGotInitialUpdate || mItems.size() == 0)
146		{
147			// Purge forward items (if any).
148			if(mItems.size())
149				mItems.erase (mItems.begin() + mCurrentItem + 1, mItems.end());
150			
151			// Append an empty item to the history and make it current.
152			mItems.push_back(LLTeleportHistoryItem("", LLVector3d()));
153			mCurrentItem++;
154		}
155
156		// Update current history item.
157		if (mCurrentItem < 0 || mCurrentItem >= (int) mItems.size()) // sanity check
158		{
159			llwarns << "Invalid current item. (this should not happen)" << llendl;
160			llassert(!"Invalid current teleport history item");
161			return;
162		}
163		LLVector3 new_pos_local = gAgent.getPosAgentFromGlobal(new_pos);
164		mItems[mCurrentItem].mFullTitle = getCurrentLocationTitle(true, new_pos_local);
165		mItems[mCurrentItem].mTitle = getCurrentLocationTitle(false, new_pos_local);
166		mItems[mCurrentItem].mGlobalPos	= new_pos;
167		mItems[mCurrentItem].mRegionID = gAgent.getRegion()->getRegionID();
168	}
169
170	dump();
171	
172	if (!mGotInitialUpdate)
173		mGotInitialUpdate = true;
174
175	// Signal the interesting party that we've changed. 
176	onHistoryChanged();
177}
178
179boost::signals2::connection LLTeleportHistory::setHistoryChangedCallback(history_callback_t cb)
180{
181	return mHistoryChangedSignal.connect(cb);
182}
183
184void LLTeleportHistory::onHistoryChanged()
185{
186	mHistoryChangedSignal();
187}
188
189void LLTeleportHistory::purgeItems()
190{
191	if (mItems.size() == 0) // no entries yet (we're called before login)
192	{
193		// If we don't return here the history will get into inconsistent state, hence:
194		// 1) updateCurrentLocation() will malfunction,
195		//    so further teleports will not properly update the history;
196		// 2) mHistoryChangedSignal subscribers will be notified
197		//    of such an invalid change. (EXT-6798)
198		// Both should not happen.
199		return;
200	}
201
202	if (mItems.size() > 0)
203	{
204		mItems.erase(mItems.begin(), mItems.end()-1);
205	}
206	// reset the count
207	mRequestedItem = -1;
208	mCurrentItem = 0;
209
210	onHistoryChanged();
211}
212
213// static
214std::string LLTeleportHistory::getCurrentLocationTitle(bool full, const LLVector3& local_pos_override)
215{
216	std::string location_name;
217	LLAgentUI::ELocationFormat fmt = full ? LLAgentUI::LOCATION_FORMAT_NO_MATURITY : LLAgentUI::LOCATION_FORMAT_NORMAL;
218
219	if (!LLAgentUI::buildLocationString(location_name, fmt, local_pos_override)) location_name = "Unknown";
220	return location_name;
221}
222
223void LLTeleportHistory::dump() const
224{
225	llinfos << "Teleport history dump (" << mItems.size() << " items):" << llendl;
226	
227	for (size_t i=0; i<mItems.size(); i++)
228	{
229		std::stringstream line;
230		line << ((i == mCurrentItem) ? " * " : "   ");
231		line << i << ": " << mItems[i].mTitle;
232		line << " REGION_ID: " << mItems[i].mRegionID;
233		line << ", pos: " << mItems[i].mGlobalPos;
234		llinfos << line.str() << llendl;
235	}
236}