PageRenderTime 774ms CodeModel.GetById 262ms app.highlight 236ms RepoModel.GetById 271ms app.codeStats 0ms

/indra/newview/lllandmarkactions.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 420 lines | 324 code | 59 blank | 37 comment | 46 complexity | b9cc38bb989580fa2de28d191851ef72 MD5 | raw file
  1/** 
  2* @file lllandmarkactions.cpp
  3* @brief LLLandmarkActions class implementation
  4*
  5* $LicenseInfo:firstyear=2001&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#include "lllandmarkactions.h"
 29
 30#include "roles_constants.h"
 31
 32#include "llinventory.h"
 33#include "llinventoryfunctions.h"
 34#include "lllandmark.h"
 35#include "llparcel.h"
 36#include "llregionhandle.h"
 37
 38#include "llnotificationsutil.h"
 39
 40#include "llagent.h"
 41#include "llagentui.h"
 42#include "llinventorymodel.h"
 43#include "lllandmarklist.h"
 44#include "llslurl.h"
 45#include "llstring.h"
 46#include "llviewerinventory.h"
 47#include "llviewerparcelmgr.h"
 48#include "llworldmapmessage.h"
 49#include "llviewerwindow.h"
 50#include "llwindow.h"
 51#include "llworldmap.h"
 52
 53void copy_slurl_to_clipboard_callback(const std::string& slurl);
 54
 55class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor
 56{
 57private:
 58	LLVector3d mPos;
 59public:
 60	LLFetchlLandmarkByPos(const LLVector3d& pos) :
 61		mPos(pos)
 62	{}
 63
 64	/*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 65	{
 66		if (!item || item->getType() != LLAssetType::AT_LANDMARK)
 67			return false;
 68
 69		LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
 70		if (!landmark) // the landmark not been loaded yet
 71			return false;
 72
 73		LLVector3d landmark_global_pos;
 74		if (!landmark->getGlobalPos(landmark_global_pos))
 75			return false;
 76		//we have to round off each coordinates to compare positions properly
 77		return llround(mPos.mdV[VX]) ==  llround(landmark_global_pos.mdV[VX])
 78				&& llround(mPos.mdV[VY]) ==  llround(landmark_global_pos.mdV[VY])
 79				&& llround(mPos.mdV[VZ]) ==  llround(landmark_global_pos.mdV[VZ]);
 80	}
 81};
 82
 83class LLFetchLandmarksByName : public LLInventoryCollectFunctor
 84{
 85private:
 86	std::string name;
 87	BOOL use_substring;
 88	//this member will be contain copy of founded items to keep the result unique
 89	std::set<std::string> check_duplicate;
 90
 91public:
 92LLFetchLandmarksByName(std::string &landmark_name, BOOL if_use_substring)
 93:name(landmark_name),
 94use_substring(if_use_substring)
 95	{
 96	LLStringUtil::toLower(name);
 97	}
 98
 99public:
100	/*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
101	{
102		if (!item || item->getType() != LLAssetType::AT_LANDMARK)
103			return false;
104
105		LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
106		if (!landmark) // the landmark not been loaded yet
107			return false;
108
109		bool acceptable = false;
110		std::string landmark_name = item->getName();
111		LLStringUtil::toLower(landmark_name);
112		if(use_substring)
113		{
114			acceptable =  landmark_name.find( name ) != std::string::npos;
115		}
116		else
117		{
118			acceptable = landmark_name == name;
119		}
120		if(acceptable){
121			if(check_duplicate.find(landmark_name) != check_duplicate.end()){
122				// we have duplicated items in landmarks
123				acceptable = false;
124			}else{
125				check_duplicate.insert(landmark_name);
126			}
127		}
128
129		return acceptable;
130	}
131};
132
133// Returns true if the given inventory item is a landmark pointing to the current parcel.
134// Used to find out if there is at least one landmark from current parcel.
135class LLFirstAgentParcelLandmark : public LLInventoryCollectFunctor
136{
137private:	
138	bool mFounded;// to avoid unnecessary  check
139	
140public:
141	LLFirstAgentParcelLandmark(): mFounded(false){}
142	
143	/*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
144	{
145		if (mFounded || !item || item->getType() != LLAssetType::AT_LANDMARK)
146			return false;
147
148		LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
149		if (!landmark) // the landmark not been loaded yet
150			return false;
151
152		LLVector3d landmark_global_pos;
153		if (!landmark->getGlobalPos(landmark_global_pos))
154			return false;
155		mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos);
156		return mFounded;
157	}
158};
159
160static void fetch_landmarks(LLInventoryModel::cat_array_t& cats,
161							LLInventoryModel::item_array_t& items,
162							LLInventoryCollectFunctor& add)
163{
164	// Look in "My Favorites"
165	const LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
166	gInventory.collectDescendentsIf(favorites_folder_id,
167		cats,
168		items,
169		LLInventoryModel::EXCLUDE_TRASH,
170		add);
171
172	// Look in "Landmarks"
173	const LLUUID landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
174	gInventory.collectDescendentsIf(landmarks_folder_id,
175		cats,
176		items,
177		LLInventoryModel::EXCLUDE_TRASH,
178		add);
179}
180
181LLInventoryModel::item_array_t LLLandmarkActions::fetchLandmarksByName(std::string& name, BOOL use_substring)
182{
183	LLInventoryModel::cat_array_t cats;
184	LLInventoryModel::item_array_t items;
185	LLFetchLandmarksByName by_name(name, use_substring);
186	fetch_landmarks(cats, items, by_name);
187
188	return items;
189}
190
191bool LLLandmarkActions::landmarkAlreadyExists()
192{
193	// Determine whether there are landmarks pointing to the current global  agent position.
194	return findLandmarkForAgentPos() != NULL;
195}
196
197//static
198bool LLLandmarkActions::hasParcelLandmark()
199{
200	LLFirstAgentParcelLandmark get_first_agent_landmark;
201	LLInventoryModel::cat_array_t cats;
202	LLInventoryModel::item_array_t items;
203	fetch_landmarks(cats, items, get_first_agent_landmark);
204	return !items.empty();
205	
206}
207
208// *TODO: This could be made more efficient by only fetching the FIRST
209// landmark that meets the criteria
210LLViewerInventoryItem* LLLandmarkActions::findLandmarkForGlobalPos(const LLVector3d &pos)
211{
212	// Determine whether there are landmarks pointing to the current parcel.
213	LLInventoryModel::cat_array_t cats;
214	LLInventoryModel::item_array_t items;
215	LLFetchlLandmarkByPos is_current_pos_landmark(pos);
216	fetch_landmarks(cats, items, is_current_pos_landmark);
217
218	if(items.empty())
219	{
220		return NULL;
221	}
222
223	return items[0];
224}
225
226LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos()
227{
228	return findLandmarkForGlobalPos(gAgent.getPositionGlobal());
229}
230
231bool LLLandmarkActions::canCreateLandmarkHere()
232{
233	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
234	if(!agent_parcel)
235	{
236		llwarns << "No agent region" << llendl;
237		return false;
238	}
239	if (agent_parcel->getAllowLandmark()
240		|| LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK))
241	{
242		return true;
243	}
244
245	return false;
246}
247
248void LLLandmarkActions::createLandmarkHere(
249	const std::string& name, 
250	const std::string& desc, 
251	const LLUUID& folder_id)
252{
253	if(!gAgent.getRegion())
254	{
255		llwarns << "No agent region" << llendl;
256		return;
257	}
258	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
259	if (!agent_parcel)
260	{
261		llwarns << "No agent parcel" << llendl;
262		return;
263	}
264	if (!canCreateLandmarkHere())
265	{
266		LLNotificationsUtil::add("CannotCreateLandmarkNotOwner");
267		return;
268	}
269
270	create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
271		folder_id, LLTransactionID::tnull,
272		name, desc,
273		LLAssetType::AT_LANDMARK,
274		LLInventoryType::IT_LANDMARK,
275		NOT_WEARABLE, PERM_ALL, 
276		NULL);
277}
278
279void LLLandmarkActions::createLandmarkHere()
280{
281	std::string landmark_name, landmark_desc;
282
283	LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK);
284	LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL);
285	const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
286
287	createLandmarkHere(landmark_name, landmark_desc, folder_id);
288}
289
290void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped /* = true */)
291{
292	std::string sim_name;
293	bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal(global_pos, sim_name);
294	if (gotSimName)
295	{
296	  std::string slurl = LLSLURL(sim_name, global_pos).getSLURLString();
297		cb(slurl);
298
299		return;
300	}
301	else
302	{
303		U64 new_region_handle = to_region_handle(global_pos);
304
305		LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL,
306														cb,
307														global_pos,
308														escaped,
309														_2);
310
311		LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
312	}
313}
314
315void LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb)
316{
317	std::string sim_name;
318	LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos);
319	if (sim_infop)
320	{
321		LLVector3 pos = sim_infop->getLocalPos(global_pos);
322		std::string name = sim_infop->getName() ;
323		cb(name, llround(pos.mV[VX]), llround(pos.mV[VY]),llround(pos.mV[VZ]));
324	}
325	else
326	{
327		U64 new_region_handle = to_region_handle(global_pos);
328
329		LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords,
330														cb,
331														global_pos,
332														_1);
333
334		LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
335	}
336}
337
338void LLLandmarkActions::onRegionResponseSLURL(slurl_callback_t cb,
339										 const LLVector3d& global_pos,
340										 bool escaped,
341										 const std::string& url)
342{
343	std::string sim_name;
344	std::string slurl;
345	bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal(global_pos, sim_name);
346	if (gotSimName)
347	{
348	  slurl = LLSLURL(sim_name, global_pos).getSLURLString();
349	}
350	else
351	{
352		slurl = "";
353	}
354
355	cb(slurl);
356}
357
358void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb,
359										 const LLVector3d& global_pos,
360										 U64 region_handle)
361{
362	LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromHandle(region_handle);
363	if (sim_infop)
364	{
365		LLVector3 local_pos = sim_infop->getLocalPos(global_pos);
366		std::string name = sim_infop->getName() ;
367		cb(name, llround(local_pos.mV[VX]), llround(local_pos.mV[VY]), llround(local_pos.mV[VZ]));
368	}
369}
370
371bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)
372{
373	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
374	if (NULL == item)
375		return false;
376
377	const LLUUID& asset_id = item->getAssetUUID();
378
379	LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL);
380	if (NULL == landmark)
381		return false;
382
383	return landmark->getGlobalPos(posGlobal);
384}
385
386LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb)
387{
388	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
389	if (NULL == item)
390		return NULL;
391
392	const LLUUID& asset_id = item->getAssetUUID();
393
394	LLLandmark* landmark = gLandmarkList.getAsset(asset_id, cb);
395	if (landmark)
396	{
397		return landmark;
398	}
399
400	return NULL;
401}
402
403void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID)
404{
405	LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
406	if(landmark)
407	{
408		LLVector3d global_pos;
409		landmark->getGlobalPos(global_pos);
410		LLLandmarkActions::getSLURLfromPosGlobal(global_pos,&copy_slurl_to_clipboard_callback,true);
411	}
412}
413
414void copy_slurl_to_clipboard_callback(const std::string& slurl)
415{
416	gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
417	LLSD args;
418	args["SLURL"] = slurl;
419	LLNotificationsUtil::add("CopySLURL", args);
420}