lllandmark.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:7k
- /**
- * @file lllandmark.cpp
- * @brief Landmark asset class
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2010, 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 "linden_common.h"
- #include "lllandmark.h"
- #include <errno.h>
- #include "message.h"
- #include "llregionhandle.h"
- std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
- LLLandmark::region_map_t LLLandmark::mRegions;
- LLLandmark::region_callback_map_t LLLandmark::sRegionCallbackMap;
- LLLandmark::LLLandmark() :
- mGlobalPositionKnown(false)
- {
- }
- LLLandmark::LLLandmark(const LLVector3d& pos) :
- mGlobalPositionKnown(true),
- mGlobalPos( pos )
- {
- }
- bool LLLandmark::getGlobalPos(LLVector3d& pos)
- {
- if(mGlobalPositionKnown)
- {
- pos = mGlobalPos;
- }
- else if(mRegionID.notNull())
- {
- F32 g_x = -1.0;
- F32 g_y = -1.0;
- if(mRegionID == mLocalRegion.first)
- {
- from_region_handle(mLocalRegion.second, &g_x, &g_y);
- }
- else
- {
- region_map_t::iterator it = mRegions.find(mRegionID);
- if(it != mRegions.end())
- {
- from_region_handle((*it).second.mRegionHandle, &g_x, &g_y);
- }
- }
- if((g_x > 0.f) && (g_y > 0.f))
- {
- pos.mdV[0] = g_x + mRegionPos.mV[0];
- pos.mdV[1] = g_y + mRegionPos.mV[1];
- pos.mdV[2] = mRegionPos.mV[2];
- setGlobalPos(pos);
- }
- }
- return mGlobalPositionKnown;
- }
- void LLLandmark::setGlobalPos(const LLVector3d& pos)
- {
- mGlobalPos = pos;
- mGlobalPositionKnown = true;
- }
- bool LLLandmark::getRegionID(LLUUID& region_id)
- {
- if(mRegionID.notNull())
- {
- region_id = mRegionID;
- return true;
- }
- return false;
- }
- LLVector3 LLLandmark::getRegionPos() const
- {
- return mRegionPos;
- }
- // static
- LLLandmark* LLLandmark::constructFromString(const char *buffer)
- {
- const char* cur = buffer;
- S32 chars_read = 0;
- S32 count = 0;
- U32 version = 0;
- // read version
- count = sscanf( cur, "Landmark version %un%n", &version, &chars_read );
- if(count != 1)
- {
- goto error;
- }
- if(version == 1)
- {
- LLVector3d pos;
- cur += chars_read;
- // read position
- count = sscanf( cur, "position %lf %lf %lfn%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read );
- if( count != 3 )
- {
- goto error;
- }
- cur += chars_read;
- // llinfos << "Landmark read: " << pos << llendl;
-
- return new LLLandmark(pos);
- }
- else if(version == 2)
- {
- // *NOTE: Changing the buffer size will require changing the
- // scanf call below.
- char region_id_str[MAX_STRING]; /* Flawfinder: ignore */
- LLVector3 pos;
- cur += chars_read;
- count = sscanf( /* Flawfinder: ignore */
- cur,
- "region_id %254sn%n",
- region_id_str, &chars_read);
- if(count != 1) goto error;
- cur += chars_read;
- count = sscanf(cur, "local_pos %f %f %fn%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read);
- if(count != 3) goto error;
- cur += chars_read;
- LLLandmark* lm = new LLLandmark;
- lm->mRegionID.set(region_id_str);
- lm->mRegionPos = pos;
- return lm;
- }
- error:
- llinfos << "Bad Landmark Asset: bad _DATA_ block." << llendl;
- return NULL;
- }
- // static
- void LLLandmark::registerCallbacks(LLMessageSystem* msg)
- {
- msg->setHandlerFunc("RegionIDAndHandleReply", &processRegionIDAndHandle);
- }
- // static
- void LLLandmark::requestRegionHandle(
- LLMessageSystem* msg,
- const LLHost& upstream_host,
- const LLUUID& region_id,
- region_handle_callback_t callback)
- {
- if(region_id.isNull())
- {
- // don't bother with checking - it's 0.
- lldebugs << "requestRegionHandle: null" << llendl;
- if(callback)
- {
- const U64 U64_ZERO = 0;
- callback(region_id, U64_ZERO);
- }
- }
- else
- {
- if(region_id == mLocalRegion.first)
- {
- lldebugs << "requestRegionHandle: local" << llendl;
- if(callback)
- {
- callback(region_id, mLocalRegion.second);
- }
- }
- else
- {
- region_map_t::iterator it = mRegions.find(region_id);
- if(it == mRegions.end())
- {
- lldebugs << "requestRegionHandle: upstream" << llendl;
- if(callback)
- {
- region_callback_map_t::value_type vt(region_id, callback);
- sRegionCallbackMap.insert(vt);
- }
- lldebugs << "Landmark requesting information about: "
- << region_id << llendl;
- msg->newMessage("RegionHandleRequest");
- msg->nextBlock("RequestBlock");
- msg->addUUID("RegionID", region_id);
- msg->sendReliable(upstream_host);
- }
- else if(callback)
- {
- // we have the answer locally - just call the callack.
- lldebugs << "requestRegionHandle: ready" << llendl;
- callback(region_id, (*it).second.mRegionHandle);
- }
- }
- }
- // As good a place as any to expire old entries.
- expireOldEntries();
- }
- // static
- void LLLandmark::setRegionHandle(const LLUUID& region_id, U64 region_handle)
- {
- mLocalRegion.first = region_id;
- mLocalRegion.second = region_handle;
- }
- // static
- void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
- {
- LLUUID region_id;
- msg->getUUID("ReplyBlock", "RegionID", region_id);
- mRegions.erase(region_id);
- CacheInfo info;
- const F32 CACHE_EXPIRY_SECONDS = 60.0f * 10.0f; // ten minutes
- info.mTimer.setTimerExpirySec(CACHE_EXPIRY_SECONDS);
- msg->getU64("ReplyBlock", "RegionHandle", info.mRegionHandle);
- region_map_t::value_type vt(region_id, info);
- mRegions.insert(vt);
- #if LL_DEBUG
- U32 grid_x, grid_y;
- grid_from_region_handle(info.mRegionHandle, &grid_x, &grid_y);
- lldebugs << "Landmark got reply for region: " << region_id << " "
- << grid_x << "," << grid_y << llendl;
- #endif
- // make all the callbacks here.
- region_callback_map_t::iterator it;
- while((it = sRegionCallbackMap.find(region_id)) != sRegionCallbackMap.end())
- {
- (*it).second(region_id, info.mRegionHandle);
- sRegionCallbackMap.erase(it);
- }
- }
- // static
- void LLLandmark::expireOldEntries()
- {
- for(region_map_t::iterator it = mRegions.begin(); it != mRegions.end(); )
- {
- if((*it).second.mTimer.hasExpired())
- {
- mRegions.erase(it++);
- }
- else
- {
- ++it;
- }
- }
- }