From cbebd682f7b9b0cff120bc36d9db9bb170dc1b2a Mon Sep 17 00:00:00 2001 From: Todd Stinson Date: Wed, 25 Apr 2012 13:04:13 -0700 Subject: Removing windows line endings from .h and .cpp files. --- indra/llcommon/llsdserialize.cpp | 4498 +++++++++++----------- indra/llprimitive/object_flags.h | 150 +- indra/newview/llfloaterpathfindingbasic.cpp | 334 +- indra/newview/llfloaterpathfindingcharacters.cpp | 1116 +++--- indra/newview/llfloaterpathfindingcharacters.h | 256 +- indra/newview/llfloaterpathfindinglinksets.cpp | 2518 ++++++------ indra/newview/llfloaterpathfindinglinksets.h | 368 +- indra/newview/llpanelvolume.cpp | 16 +- indra/newview/llpathfindingcharacter.cpp | 206 +- indra/newview/llpathfindingcharacter.h | 140 +- indra/newview/llpathfindingcharacterlist.cpp | 126 +- indra/newview/llpathfindingcharacterlist.h | 112 +- indra/newview/llpathfindinglinkset.cpp | 1044 ++--- indra/newview/llpathfindinglinkset.h | 264 +- indra/newview/llpathfindinglinksetlist.cpp | 244 +- indra/newview/llpathfindinglinksetlist.h | 122 +- indra/newview/llpathfindingnavmeshstatus.cpp | 318 +- indra/newview/llpathfindingnavmeshstatus.h | 170 +- indra/newview/llpathfindingpathtool.cpp | 858 ++--- indra/newview/llpathfindingpathtool.h | 272 +- indra/newview/llworld.cpp | 2476 ++++++------ 21 files changed, 7804 insertions(+), 7804 deletions(-) diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index bc66832ad0..7f4f670ed0 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -1,2249 +1,2249 @@ -/** - * @file llsdserialize.cpp - * @author Phoenix - * @date 2006-03-05 - * @brief Implementation of LLSD parsers and formatters - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llsdserialize.h" -#include "llpointer.h" -#include "llstreamtools.h" // for fullread - -#include -#include "apr_base64.h" - -#ifdef LL_STANDALONE -# include -#else -# include "zlib/zlib.h" // for davep's dirty little zip functions -#endif - -#if !LL_WINDOWS -#include // htonl & ntohl -#endif - -#include "lldate.h" -#include "llsd.h" -#include "llstring.h" -#include "lluri.h" - -// File constants -static const int MAX_HDR_LEN = 20; -static const char LEGACY_NON_HEADER[] = ""; -const std::string LLSD_BINARY_HEADER("LLSD/Binary"); -const std::string LLSD_XML_HEADER("LLSD/XML"); - -//used to deflate a gzipped asset (currently used for navmeshes) -#define windowBits 15 -#define ENABLE_ZLIB_GZIP 32 - -/** - * LLSDSerialize - */ - -// static -void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options) -{ - LLPointer f = NULL; - - switch (type) - { - case LLSD_BINARY: - str << "\n"; - f = new LLSDBinaryFormatter; - break; - - case LLSD_XML: - str << "\n"; - f = new LLSDXMLFormatter; - break; - - default: - llwarns << "serialize request for unknown ELLSD_Serialize" << llendl; - } - - if (f.notNull()) - { - f->format(sd, str, options); - } -} - -// static -bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) -{ - LLPointer p = NULL; - char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ - int i; - int inbuf = 0; - bool legacy_no_header = false; - bool fail_if_not_legacy = false; - std::string header; - - /* - * Get the first line before anything. - */ - str.get(hdr_buf, MAX_HDR_LEN, '\n'); - if (str.fail()) - { - str.clear(); - fail_if_not_legacy = true; - } - - if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ - { - legacy_no_header = true; - inbuf = (int)str.gcount(); - } - else - { - if (fail_if_not_legacy) - goto fail; - /* - * Remove the newline chars - */ - for (i = 0; i < MAX_HDR_LEN; i++) - { - if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' || - hdr_buf[i] == '\n') - { - hdr_buf[i] = 0; - break; - } - } - header = hdr_buf; - - std::string::size_type start = std::string::npos; - std::string::size_type end = std::string::npos; - start = header.find_first_not_of("parsePart(hdr_buf, inbuf); // Parse the first part that was already read - x->parseLines(str, sd); // Parse the rest of it - delete x; - return true; - } - - if (header == LLSD_BINARY_HEADER) - { - p = new LLSDBinaryParser; - } - else if (header == LLSD_XML_HEADER) - { - p = new LLSDXMLParser; - } - else - { - llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl; - } - - if (p.notNull()) - { - p->parse(str, sd, max_bytes); - return true; - } - -fail: - llwarns << "deserialize LLSD parse failure" << llendl; - return false; -} - -/** - * Endian handlers - */ -#if LL_BIG_ENDIAN -U64 ll_htonll(U64 hostlonglong) { return hostlonglong; } -U64 ll_ntohll(U64 netlonglong) { return netlonglong; } -F64 ll_htond(F64 hostlonglong) { return hostlonglong; } -F64 ll_ntohd(F64 netlonglong) { return netlonglong; } -#else -// I read some comments one a indicating that doing an integer add -// here would be faster than a bitwise or. For now, the or has -// programmer clarity, since the intended outcome matches the -// operation. -U64 ll_htonll(U64 hostlonglong) -{ - return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) | - ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32)); -} -U64 ll_ntohll(U64 netlonglong) -{ - return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) | - ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32)); -} -union LLEndianSwapper -{ - F64 d; - U64 i; -}; -F64 ll_htond(F64 hostdouble) -{ - LLEndianSwapper tmp; - tmp.d = hostdouble; - tmp.i = ll_htonll(tmp.i); - return tmp.d; -} -F64 ll_ntohd(F64 netdouble) -{ - LLEndianSwapper tmp; - tmp.d = netdouble; - tmp.i = ll_ntohll(tmp.i); - return tmp.d; -} -#endif - -/** - * Local functions. - */ -/** - * @brief Figure out what kind of string it is (raw or delimited) and handoff. - * - * @param istr The stream to read from. - * @param value [out] The string which was found. - * @param max_bytes The maximum possible length of the string. Passing in - * a negative value will skip this check. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes); - -/** - * @brief Parse a delimited string. - * - * @param istr The stream to read from, with the delimiter already popped. - * @param value [out] The string which was found. - * @param d The delimiter to use. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string_delim(std::istream& istr, std::string& value, char d); - -/** - * @brief Read a raw string off the stream. - * - * @param istr The stream to read from, with the (len) parameter - * leading the stream. - * @param value [out] The string which was found. - * @param d The delimiter to use. - * @param max_bytes The maximum possible length of the string. Passing in - * a negative value will skip this check. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string_raw( - std::istream& istr, - std::string& value, - S32 max_bytes); - -/** - * @brief helper method for dealing with the different notation boolean format. - * - * @param istr The stream to read from with the leading character stripped. - * @param data [out] the result of the parse. - * @param compare The string to compare the boolean against - * @param vale The value to assign to data if the parse succeeds. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_boolean( - std::istream& istr, - LLSD& data, - const std::string& compare, - bool value); - -/** - * @brief Do notation escaping of a string to an ostream. - * - * @param value The string to escape and serialize - * @param str The stream to serialize to. - */ -void serialize_string(const std::string& value, std::ostream& str); - - -/** - * Local constants. - */ -static const std::string NOTATION_TRUE_SERIAL("true"); -static const std::string NOTATION_FALSE_SERIAL("false"); - -static const char BINARY_TRUE_SERIAL = '1'; -static const char BINARY_FALSE_SERIAL = '0'; - - -/** - * LLSDParser - */ -LLSDParser::LLSDParser() - : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false) -{ -} - -// virtual -LLSDParser::~LLSDParser() -{ } - -S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes) -{ - mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; - mMaxBytesLeft = max_bytes; - return doParse(istr, data); -} - - -// Parse using routine to get() lines, faster than parse() -S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) -{ - mCheckLimits = false; - mParseLines = true; - return doParse(istr, data); -} - - -int LLSDParser::get(std::istream& istr) const -{ - if(mCheckLimits) --mMaxBytesLeft; - return istr.get(); -} - -std::istream& LLSDParser::get( - std::istream& istr, - char* s, - std::streamsize n, - char delim) const -{ - istr.get(s, n, delim); - if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); - return istr; -} - -std::istream& LLSDParser::get( - std::istream& istr, - std::streambuf& sb, - char delim) const -{ - istr.get(sb, delim); - if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); - return istr; -} - -std::istream& LLSDParser::ignore(std::istream& istr) const -{ - istr.ignore(); - if(mCheckLimits) --mMaxBytesLeft; - return istr; -} - -std::istream& LLSDParser::putback(std::istream& istr, char c) const -{ - istr.putback(c); - if(mCheckLimits) ++mMaxBytesLeft; - return istr; -} - -std::istream& LLSDParser::read( - std::istream& istr, - char* s, - std::streamsize n) const -{ - istr.read(s, n); - if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); - return istr; -} - -void LLSDParser::account(S32 bytes) const -{ - if(mCheckLimits) mMaxBytesLeft -= bytes; -} - - -/** - * LLSDNotationParser - */ -LLSDNotationParser::LLSDNotationParser() -{ -} - -// virtual -LLSDNotationParser::~LLSDNotationParser() -{ } - -// virtual -S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const -{ - // map: { string:object, string:object } - // array: [ object, object, object ] - // undef: ! - // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE - // integer: i#### - // real: r#### - // uuid: u#### - // string: "g'day" | 'have a "nice" day' | s(size)"raw data" - // uri: l"escaped" - // date: d"YYYY-MM-DDTHH:MM:SS.FFZ" - // binary: b##"ff3120ab1" | b(size)"raw data" - char c; - c = istr.peek(); - while(isspace(c)) - { - // pop the whitespace. - c = get(istr); - c = istr.peek(); - continue; - } - if(!istr.good()) - { - return 0; - } - S32 parse_count = 1; - switch(c) - { - case '{': - { - S32 child_count = parseMap(istr, data); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading map." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case '[': - { - S32 child_count = parseArray(istr, data); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading array." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case '!': - c = get(istr); - data.clear(); - break; - - case '0': - c = get(istr); - data = false; - break; - - case 'F': - case 'f': - ignore(istr); - c = istr.peek(); - if(isalpha(c)) - { - int cnt = deserialize_boolean( - istr, - data, - NOTATION_FALSE_SERIAL, - false); - if(PARSE_FAILURE == cnt) parse_count = cnt; - else account(cnt); - } - else - { - data = false; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading boolean." << llendl; - parse_count = PARSE_FAILURE; - } - break; - - case '1': - c = get(istr); - data = true; - break; - - case 'T': - case 't': - ignore(istr); - c = istr.peek(); - if(isalpha(c)) - { - int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true); - if(PARSE_FAILURE == cnt) parse_count = cnt; - else account(cnt); - } - else - { - data = true; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading boolean." << llendl; - parse_count = PARSE_FAILURE; - } - break; - - case 'i': - { - c = get(istr); - S32 integer = 0; - istr >> integer; - data = integer; - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading integer." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'r': - { - c = get(istr); - F64 real = 0.0; - istr >> real; - data = real; - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading real." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'u': - { - c = get(istr); - LLUUID id; - istr >> id; - data = id; - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading uuid." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case '\"': - case '\'': - case 's': - if(!parseString(istr, data)) - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading string." << llendl; - parse_count = PARSE_FAILURE; - } - break; - - case 'l': - { - c = get(istr); // pop the 'l' - c = get(istr); // pop the delimiter - std::string str; - int cnt = deserialize_string_delim(istr, str, c); - if(PARSE_FAILURE == cnt) - { - parse_count = PARSE_FAILURE; - } - else - { - data = LLURI(str); - account(cnt); - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading link." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'd': - { - c = get(istr); // pop the 'd' - c = get(istr); // pop the delimiter - std::string str; - int cnt = deserialize_string_delim(istr, str, c); - if(PARSE_FAILURE == cnt) - { - parse_count = PARSE_FAILURE; - } - else - { - data = LLDate(str); - account(cnt); - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading date." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'b': - if(!parseBinary(istr, data)) - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading data." << llendl; - parse_count = PARSE_FAILURE; - } - break; - - default: - parse_count = PARSE_FAILURE; - llinfos << "Unrecognized character while parsing: int(" << (int)c - << ")" << llendl; - break; - } - if(PARSE_FAILURE == parse_count) - { - data.clear(); - } - return parse_count; -} - -S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const -{ - // map: { string:object, string:object } - map = LLSD::emptyMap(); - S32 parse_count = 0; - char c = get(istr); - if(c == '{') - { - // eat commas, white - bool found_name = false; - std::string name; - c = get(istr); - while(c != '}' && istr.good()) - { - if(!found_name) - { - if((c == '\"') || (c == '\'') || (c == 's')) - { - putback(istr, c); - found_name = true; - int count = deserialize_string(istr, name, mMaxBytesLeft); - if(PARSE_FAILURE == count) return PARSE_FAILURE; - account(count); - } - c = get(istr); - } - else - { - if(isspace(c) || (c == ':')) - { - c = get(istr); - continue; - } - putback(istr, c); - LLSD child; - S32 count = doParse(istr, child); - if(count > 0) - { - // There must be a value for every key, thus - // child_count must be greater than 0. - parse_count += count; - map.insert(name, child); - } - else - { - return PARSE_FAILURE; - } - found_name = false; - c = get(istr); - } - } - if(c != '}') - { - map.clear(); - return PARSE_FAILURE; - } - } - return parse_count; -} - -S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const -{ - // array: [ object, object, object ] - array = LLSD::emptyArray(); - S32 parse_count = 0; - char c = get(istr); - if(c == '[') - { - // eat commas, white - c = get(istr); - while((c != ']') && istr.good()) - { - LLSD child; - if(isspace(c) || (c == ',')) - { - c = get(istr); - continue; - } - putback(istr, c); - S32 count = doParse(istr, child); - if(PARSE_FAILURE == count) - { - return PARSE_FAILURE; - } - else - { - parse_count += count; - array.append(child); - } - c = get(istr); - } - if(c != ']') - { - return PARSE_FAILURE; - } - } - return parse_count; -} - -bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const -{ - std::string value; - int count = deserialize_string(istr, value, mMaxBytesLeft); - if(PARSE_FAILURE == count) return false; - account(count); - data = value; - return true; -} - -bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const -{ - // binary: b##"ff3120ab1" - // or: b(len)"..." - - // I want to manually control those values here to make sure the - // parser doesn't break when someone changes a constant somewhere - // else. - const U32 BINARY_BUFFER_SIZE = 256; - const U32 STREAM_GET_COUNT = 255; - - // need to read the base out. - char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */ - get(istr, buf, STREAM_GET_COUNT, '"'); - char c = get(istr); - if(c != '"') return false; - if(0 == strncmp("b(", buf, 2)) - { - // We probably have a valid raw binary stream. determine - // the size, and read it. - S32 len = strtol(buf + 2, NULL, 0); - if(mCheckLimits && (len > mMaxBytesLeft)) return false; - std::vector value; - if(len) - { - value.resize(len); - account((int)fullread(istr, (char *)&value[0], len)); - } - c = get(istr); // strip off the trailing double-quote - data = value; - } - else if(0 == strncmp("b64", buf, 3)) - { - // *FIX: A bit inefficient, but works for now. To make the - // format better, I would need to add a hint into the - // serialization format that indicated how long it was. - std::stringstream coded_stream; - get(istr, *(coded_stream.rdbuf()), '\"'); - c = get(istr); - std::string encoded(coded_stream.str()); - S32 len = apr_base64_decode_len(encoded.c_str()); - std::vector value; - if(len) - { - value.resize(len); - len = apr_base64_decode_binary(&value[0], encoded.c_str()); - value.resize(len); - } - data = value; - } - else if(0 == strncmp("b16", buf, 3)) - { - // yay, base 16. We pop the next character which is either a - // double quote or base 16 data. If it's a double quote, we're - // done parsing. If it's not, put the data back, and read the - // stream until the next double quote. - char* read; /*Flawfinder: ignore*/ - U8 byte; - U8 byte_buffer[BINARY_BUFFER_SIZE]; - U8* write; - std::vector value; - c = get(istr); - while(c != '"') - { - putback(istr, c); - read = buf; - write = byte_buffer; - get(istr, buf, STREAM_GET_COUNT, '"'); - c = get(istr); - while(*read != '\0') /*Flawfinder: ignore*/ - { - byte = hex_as_nybble(*read++); - byte = byte << 4; - byte |= hex_as_nybble(*read++); - *write++ = byte; - } - // copy the data out of the byte buffer - value.insert(value.end(), byte_buffer, write); - } - data = value; - } - else - { - return false; - } - return true; -} - - -/** - * LLSDBinaryParser - */ -LLSDBinaryParser::LLSDBinaryParser() -{ -} - -// virtual -LLSDBinaryParser::~LLSDBinaryParser() -{ -} - -// virtual -S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const -{ -/** - * Undefined: '!'
- * Boolean: 't' for true 'f' for false
- * Integer: 'i' + 4 bytes network byte order
- * Real: 'r' + 8 bytes IEEE double
- * UUID: 'u' + 16 byte unsigned integer
- * String: 's' + 4 byte integer size + string
- * strings also secretly support the notation format - * Date: 'd' + 8 byte IEEE double for seconds since epoch
- * URI: 'l' + 4 byte integer size + string uri
- * Binary: 'b' + 4 byte integer size + binary data
- * Array: '[' + 4 byte integer size + all values + ']'
- * Map: '{' + 4 byte integer size every(key + value) + '}'
- * map keys are serialized as s + 4 byte integer size + string or in the - * notation format. - */ - char c; - c = get(istr); - if(!istr.good()) - { - return 0; - } - S32 parse_count = 1; - switch(c) - { - case '{': - { - S32 child_count = parseMap(istr, data); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary map." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case '[': - { - S32 child_count = parseArray(istr, data); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary array." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case '!': - data.clear(); - break; - - case '0': - data = false; - break; - - case '1': - data = true; - break; - - case 'i': - { - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - data = (S32)ntohl(value_nbo); - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary integer." << llendl; - } - break; - } - - case 'r': - { - F64 real_nbo = 0.0; - read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/ - data = ll_ntohd(real_nbo); - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary real." << llendl; - } - break; - } - - case 'u': - { - LLUUID id; - read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/ - data = id; - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary uuid." << llendl; - } - break; - } - - case '\'': - case '"': - { - std::string value; - int cnt = deserialize_string_delim(istr, value, c); - if(PARSE_FAILURE == cnt) - { - parse_count = PARSE_FAILURE; - } - else - { - data = value; - account(cnt); - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary (notation-style) string." - << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 's': - { - std::string value; - if(parseString(istr, value)) - { - data = value; - } - else - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary string." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'l': - { - std::string value; - if(parseString(istr, value)) - { - data = LLURI(value); - } - else - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary link." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'd': - { - F64 real = 0.0; - read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/ - data = LLDate(real); - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary date." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'b': - { - // We probably have a valid raw binary stream. determine - // the size, and read it. - U32 size_nbo = 0; - read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(size_nbo); - if(mCheckLimits && (size > mMaxBytesLeft)) - { - parse_count = PARSE_FAILURE; - } - else - { - std::vector value; - if(size > 0) - { - value.resize(size); - account((int)fullread(istr, (char*)&value[0], size)); - } - data = value; - } - if(istr.fail()) - { - llinfos << "STREAM FAILURE reading binary." << llendl; - parse_count = PARSE_FAILURE; - } - break; - } - - default: - parse_count = PARSE_FAILURE; - llinfos << "Unrecognized character while parsing: int(" << (int)c - << ")" << llendl; - break; - } - if(PARSE_FAILURE == parse_count) - { - data.clear(); - } - return parse_count; -} - -S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const -{ - map = LLSD::emptyMap(); - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - S32 parse_count = 0; - S32 count = 0; - char c = get(istr); - while(c != '}' && (count < size) && istr.good()) - { - std::string name; - switch(c) - { - case 'k': - if(!parseString(istr, name)) - { - return PARSE_FAILURE; - } - break; - case '\'': - case '"': - { - int cnt = deserialize_string_delim(istr, name, c); - if(PARSE_FAILURE == cnt) return PARSE_FAILURE; - account(cnt); - break; - } - } - LLSD child; - S32 child_count = doParse(istr, child); - if(child_count > 0) - { - // There must be a value for every key, thus child_count - // must be greater than 0. - parse_count += child_count; - map.insert(name, child); - } - else - { - return PARSE_FAILURE; - } - ++count; - c = get(istr); - } - if((c != '}') || (count < size)) - { - // Make sure it is correctly terminated and we parsed as many - // as were said to be there. - return PARSE_FAILURE; - } - return parse_count; -} - -S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const -{ - array = LLSD::emptyArray(); - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - - // *FIX: This would be a good place to reserve some space in the - // array... - - S32 parse_count = 0; - S32 count = 0; - char c = istr.peek(); - while((c != ']') && (count < size) && istr.good()) - { - LLSD child; - S32 child_count = doParse(istr, child); - if(PARSE_FAILURE == child_count) - { - return PARSE_FAILURE; - } - if(child_count) - { - parse_count += child_count; - array.append(child); - } - ++count; - c = istr.peek(); - } - c = get(istr); - if((c != ']') || (count < size)) - { - // Make sure it is correctly terminated and we parsed as many - // as were said to be there. - return PARSE_FAILURE; - } - return parse_count; -} - -bool LLSDBinaryParser::parseString( - std::istream& istr, - std::string& value) const -{ - // *FIX: This is memory inefficient. - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - if(mCheckLimits && (size > mMaxBytesLeft)) return false; - std::vector buf; - if(size) - { - buf.resize(size); - account((int)fullread(istr, &buf[0], size)); - value.assign(buf.begin(), buf.end()); - } - return true; -} - - -/** - * LLSDFormatter - */ -LLSDFormatter::LLSDFormatter() : - mBoolAlpha(false) -{ -} - -// virtual -LLSDFormatter::~LLSDFormatter() -{ } - -void LLSDFormatter::boolalpha(bool alpha) -{ - mBoolAlpha = alpha; -} - -void LLSDFormatter::realFormat(const std::string& format) -{ - mRealFormat = format; -} - -void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const -{ - std::string buffer = llformat(mRealFormat.c_str(), real); - ostr << buffer; -} - -/** - * LLSDNotationFormatter - */ -LLSDNotationFormatter::LLSDNotationFormatter() -{ -} - -// virtual -LLSDNotationFormatter::~LLSDNotationFormatter() -{ } - -// static -std::string LLSDNotationFormatter::escapeString(const std::string& in) -{ - std::ostringstream ostr; - serialize_string(in, ostr); - return ostr.str(); -} - -// virtual -S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const -{ - S32 format_count = 1; - switch(data.type()) - { - case LLSD::TypeMap: - { - ostr << "{"; - bool need_comma = false; - LLSD::map_const_iterator iter = data.beginMap(); - LLSD::map_const_iterator end = data.endMap(); - for(; iter != end; ++iter) - { - if(need_comma) ostr << ","; - need_comma = true; - ostr << '\''; - serialize_string((*iter).first, ostr); - ostr << "':"; - format_count += format((*iter).second, ostr); - } - ostr << "}"; - break; - } - - case LLSD::TypeArray: - { - ostr << "["; - bool need_comma = false; - LLSD::array_const_iterator iter = data.beginArray(); - LLSD::array_const_iterator end = data.endArray(); - for(; iter != end; ++iter) - { - if(need_comma) ostr << ","; - need_comma = true; - format_count += format(*iter, ostr); - } - ostr << "]"; - break; - } - - case LLSD::TypeUndefined: - ostr << "!"; - break; - - case LLSD::TypeBoolean: - if(mBoolAlpha || -#if( LL_WINDOWS || __GNUC__ > 2) - (ostr.flags() & std::ios::boolalpha) -#else - (ostr.flags() & 0x0100) -#endif - ) - { - ostr << (data.asBoolean() - ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); - } - else - { - ostr << (data.asBoolean() ? 1 : 0); - } - break; - - case LLSD::TypeInteger: - ostr << "i" << data.asInteger(); - break; - - case LLSD::TypeReal: - ostr << "r"; - if(mRealFormat.empty()) - { - ostr << data.asReal(); - } - else - { - formatReal(data.asReal(), ostr); - } - break; - - case LLSD::TypeUUID: - ostr << "u" << data.asUUID(); - break; - - case LLSD::TypeString: - ostr << '\''; - serialize_string(data.asString(), ostr); - ostr << '\''; - break; - - case LLSD::TypeDate: - ostr << "d\"" << data.asDate() << "\""; - break; - - case LLSD::TypeURI: - ostr << "l\""; - serialize_string(data.asString(), ostr); - ostr << "\""; - break; - - case LLSD::TypeBinary: - { - // *FIX: memory inefficient. - std::vector buffer = data.asBinary(); - ostr << "b(" << buffer.size() << ")\""; - if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); - ostr << "\""; - break; - } - - default: - // *NOTE: This should never happen. - ostr << "!"; - break; - } - return format_count; -} - - -/** - * LLSDBinaryFormatter - */ -LLSDBinaryFormatter::LLSDBinaryFormatter() -{ -} - -// virtual -LLSDBinaryFormatter::~LLSDBinaryFormatter() -{ } - -// virtual -S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const -{ - S32 format_count = 1; - switch(data.type()) - { - case LLSD::TypeMap: - { - ostr.put('{'); - U32 size_nbo = htonl(data.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - LLSD::map_const_iterator iter = data.beginMap(); - LLSD::map_const_iterator end = data.endMap(); - for(; iter != end; ++iter) - { - ostr.put('k'); - formatString((*iter).first, ostr); - format_count += format((*iter).second, ostr); - } - ostr.put('}'); - break; - } - - case LLSD::TypeArray: - { - ostr.put('['); - U32 size_nbo = htonl(data.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - LLSD::array_const_iterator iter = data.beginArray(); - LLSD::array_const_iterator end = data.endArray(); - for(; iter != end; ++iter) - { - format_count += format(*iter, ostr); - } - ostr.put(']'); - break; - } - - case LLSD::TypeUndefined: - ostr.put('!'); - break; - - case LLSD::TypeBoolean: - if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL); - else ostr.put(BINARY_FALSE_SERIAL); - break; - - case LLSD::TypeInteger: - { - ostr.put('i'); - U32 value_nbo = htonl(data.asInteger()); - ostr.write((const char*)(&value_nbo), sizeof(U32)); - break; - } - - case LLSD::TypeReal: - { - ostr.put('r'); - F64 value_nbo = ll_htond(data.asReal()); - ostr.write((const char*)(&value_nbo), sizeof(F64)); - break; - } - - case LLSD::TypeUUID: - ostr.put('u'); - ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES); - break; - - case LLSD::TypeString: - ostr.put('s'); - formatString(data.asString(), ostr); - break; - - case LLSD::TypeDate: - { - ostr.put('d'); - F64 value = data.asReal(); - ostr.write((const char*)(&value), sizeof(F64)); - break; - } - - case LLSD::TypeURI: - ostr.put('l'); - formatString(data.asString(), ostr); - break; - - case LLSD::TypeBinary: - { - // *FIX: memory inefficient. - ostr.put('b'); - std::vector buffer = data.asBinary(); - U32 size_nbo = htonl(buffer.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); - break; - } - - default: - // *NOTE: This should never happen. - ostr.put('!'); - break; - } - return format_count; -} - -void LLSDBinaryFormatter::formatString( - const std::string& string, - std::ostream& ostr) const -{ - U32 size_nbo = htonl(string.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - ostr.write(string.c_str(), string.size()); -} - -/** - * local functions - */ -int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes) -{ - int c = istr.get(); - if(istr.fail()) - { - // No data in stream, bail out but mention the character we - // grabbed. - return LLSDParser::PARSE_FAILURE; - } - - int rv = LLSDParser::PARSE_FAILURE; - switch(c) - { - case '\'': - case '"': - rv = deserialize_string_delim(istr, value, c); - break; - case 's': - // technically, less than max_bytes, but this is just meant to - // catch egregious protocol errors. parse errors will be - // caught in the case of incorrect counts. - rv = deserialize_string_raw(istr, value, max_bytes); - break; - default: - break; - } - if(LLSDParser::PARSE_FAILURE == rv) return rv; - return rv + 1; // account for the character grabbed at the top. -} - -int deserialize_string_delim( - std::istream& istr, - std::string& value, - char delim) -{ - std::ostringstream write_buffer; - bool found_escape = false; - bool found_hex = false; - bool found_digit = false; - U8 byte = 0; - int count = 0; - - while (true) - { - int next_byte = istr.get(); - ++count; - - if(istr.fail()) - { - // If our stream is empty, break out - value = write_buffer.str(); - return LLSDParser::PARSE_FAILURE; - } - - char next_char = (char)next_byte; // Now that we know it's not EOF - - if(found_escape) - { - // next character(s) is a special sequence. - if(found_hex) - { - if(found_digit) - { - found_digit = false; - found_hex = false; - found_escape = false; - byte = byte << 4; - byte |= hex_as_nybble(next_char); - write_buffer << byte; - byte = 0; - } - else - { - // next character is the first nybble of - // - found_digit = true; - byte = hex_as_nybble(next_char); - } - } - else if(next_char == 'x') - { - found_hex = true; - } - else - { - switch(next_char) - { - case 'a': - write_buffer << '\a'; - break; - case 'b': - write_buffer << '\b'; - break; - case 'f': - write_buffer << '\f'; - break; - case 'n': - write_buffer << '\n'; - break; - case 'r': - write_buffer << '\r'; - break; - case 't': - write_buffer << '\t'; - break; - case 'v': - write_buffer << '\v'; - break; - default: - write_buffer << next_char; - break; - } - found_escape = false; - } - } - else if(next_char == '\\') - { - found_escape = true; - } - else if(next_char == delim) - { - break; - } - else - { - write_buffer << next_char; - } - } - - value = write_buffer.str(); - return count; -} - -int deserialize_string_raw( - std::istream& istr, - std::string& value, - S32 max_bytes) -{ - int count = 0; - const S32 BUF_LEN = 20; - char buf[BUF_LEN]; /* Flawfinder: ignore */ - istr.get(buf, BUF_LEN - 1, ')'); - count += (int)istr.gcount(); - int c = istr.get(); - c = istr.get(); - count += 2; - if(((c == '"') || (c == '\'')) && (buf[0] == '(')) - { - // We probably have a valid raw string. determine - // the size, and read it. - // *FIX: This is memory inefficient. - S32 len = strtol(buf + 1, NULL, 0); - if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; - std::vector buf; - if(len) - { - buf.resize(len); - count += (int)fullread(istr, (char *)&buf[0], len); - value.assign(buf.begin(), buf.end()); - } - c = istr.get(); - ++count; - if(!((c == '"') || (c == '\''))) - { - return LLSDParser::PARSE_FAILURE; - } - } - else - { - return LLSDParser::PARSE_FAILURE; - } - return count; -} - -static const char* NOTATION_STRING_CHARACTERS[256] = -{ - "\\x00", // 0 - "\\x01", // 1 - "\\x02", // 2 - "\\x03", // 3 - "\\x04", // 4 - "\\x05", // 5 - "\\x06", // 6 - "\\a", // 7 - "\\b", // 8 - "\\t", // 9 - "\\n", // 10 - "\\v", // 11 - "\\f", // 12 - "\\r", // 13 - "\\x0e", // 14 - "\\x0f", // 15 - "\\x10", // 16 - "\\x11", // 17 - "\\x12", // 18 - "\\x13", // 19 - "\\x14", // 20 - "\\x15", // 21 - "\\x16", // 22 - "\\x17", // 23 - "\\x18", // 24 - "\\x19", // 25 - "\\x1a", // 26 - "\\x1b", // 27 - "\\x1c", // 28 - "\\x1d", // 29 - "\\x1e", // 30 - "\\x1f", // 31 - " ", // 32 - "!", // 33 - "\"", // 34 - "#", // 35 - "$", // 36 - "%", // 37 - "&", // 38 - "\\'", // 39 - "(", // 40 - ")", // 41 - "*", // 42 - "+", // 43 - ",", // 44 - "-", // 45 - ".", // 46 - "/", // 47 - "0", // 48 - "1", // 49 - "2", // 50 - "3", // 51 - "4", // 52 - "5", // 53 - "6", // 54 - "7", // 55 - "8", // 56 - "9", // 57 - ":", // 58 - ";", // 59 - "<", // 60 - "=", // 61 - ">", // 62 - "?", // 63 - "@", // 64 - "A", // 65 - "B", // 66 - "C", // 67 - "D", // 68 - "E", // 69 - "F", // 70 - "G", // 71 - "H", // 72 - "I", // 73 - "J", // 74 - "K", // 75 - "L", // 76 - "M", // 77 - "N", // 78 - "O", // 79 - "P", // 80 - "Q", // 81 - "R", // 82 - "S", // 83 - "T", // 84 - "U", // 85 - "V", // 86 - "W", // 87 - "X", // 88 - "Y", // 89 - "Z", // 90 - "[", // 91 - "\\\\", // 92 - "]", // 93 - "^", // 94 - "_", // 95 - "`", // 96 - "a", // 97 - "b", // 98 - "c", // 99 - "d", // 100 - "e", // 101 - "f", // 102 - "g", // 103 - "h", // 104 - "i", // 105 - "j", // 106 - "k", // 107 - "l", // 108 - "m", // 109 - "n", // 110 - "o", // 111 - "p", // 112 - "q", // 113 - "r", // 114 - "s", // 115 - "t", // 116 - "u", // 117 - "v", // 118 - "w", // 119 - "x", // 120 - "y", // 121 - "z", // 122 - "{", // 123 - "|", // 124 - "}", // 125 - "~", // 126 - "\\x7f", // 127 - "\\x80", // 128 - "\\x81", // 129 - "\\x82", // 130 - "\\x83", // 131 - "\\x84", // 132 - "\\x85", // 133 - "\\x86", // 134 - "\\x87", // 135 - "\\x88", // 136 - "\\x89", // 137 - "\\x8a", // 138 - "\\x8b", // 139 - "\\x8c", // 140 - "\\x8d", // 141 - "\\x8e", // 142 - "\\x8f", // 143 - "\\x90", // 144 - "\\x91", // 145 - "\\x92", // 146 - "\\x93", // 147 - "\\x94", // 148 - "\\x95", // 149 - "\\x96", // 150 - "\\x97", // 151 - "\\x98", // 152 - "\\x99", // 153 - "\\x9a", // 154 - "\\x9b", // 155 - "\\x9c", // 156 - "\\x9d", // 157 - "\\x9e", // 158 - "\\x9f", // 159 - "\\xa0", // 160 - "\\xa1", // 161 - "\\xa2", // 162 - "\\xa3", // 163 - "\\xa4", // 164 - "\\xa5", // 165 - "\\xa6", // 166 - "\\xa7", // 167 - "\\xa8", // 168 - "\\xa9", // 169 - "\\xaa", // 170 - "\\xab", // 171 - "\\xac", // 172 - "\\xad", // 173 - "\\xae", // 174 - "\\xaf", // 175 - "\\xb0", // 176 - "\\xb1", // 177 - "\\xb2", // 178 - "\\xb3", // 179 - "\\xb4", // 180 - "\\xb5", // 181 - "\\xb6", // 182 - "\\xb7", // 183 - "\\xb8", // 184 - "\\xb9", // 185 - "\\xba", // 186 - "\\xbb", // 187 - "\\xbc", // 188 - "\\xbd", // 189 - "\\xbe", // 190 - "\\xbf", // 191 - "\\xc0", // 192 - "\\xc1", // 193 - "\\xc2", // 194 - "\\xc3", // 195 - "\\xc4", // 196 - "\\xc5", // 197 - "\\xc6", // 198 - "\\xc7", // 199 - "\\xc8", // 200 - "\\xc9", // 201 - "\\xca", // 202 - "\\xcb", // 203 - "\\xcc", // 204 - "\\xcd", // 205 - "\\xce", // 206 - "\\xcf", // 207 - "\\xd0", // 208 - "\\xd1", // 209 - "\\xd2", // 210 - "\\xd3", // 211 - "\\xd4", // 212 - "\\xd5", // 213 - "\\xd6", // 214 - "\\xd7", // 215 - "\\xd8", // 216 - "\\xd9", // 217 - "\\xda", // 218 - "\\xdb", // 219 - "\\xdc", // 220 - "\\xdd", // 221 - "\\xde", // 222 - "\\xdf", // 223 - "\\xe0", // 224 - "\\xe1", // 225 - "\\xe2", // 226 - "\\xe3", // 227 - "\\xe4", // 228 - "\\xe5", // 229 - "\\xe6", // 230 - "\\xe7", // 231 - "\\xe8", // 232 - "\\xe9", // 233 - "\\xea", // 234 - "\\xeb", // 235 - "\\xec", // 236 - "\\xed", // 237 - "\\xee", // 238 - "\\xef", // 239 - "\\xf0", // 240 - "\\xf1", // 241 - "\\xf2", // 242 - "\\xf3", // 243 - "\\xf4", // 244 - "\\xf5", // 245 - "\\xf6", // 246 - "\\xf7", // 247 - "\\xf8", // 248 - "\\xf9", // 249 - "\\xfa", // 250 - "\\xfb", // 251 - "\\xfc", // 252 - "\\xfd", // 253 - "\\xfe", // 254 - "\\xff" // 255 -}; - -void serialize_string(const std::string& value, std::ostream& str) -{ - std::string::const_iterator it = value.begin(); - std::string::const_iterator end = value.end(); - U8 c; - for(; it != end; ++it) - { - c = (U8)(*it); - str << NOTATION_STRING_CHARACTERS[c]; - } -} - -int deserialize_boolean( - std::istream& istr, - LLSD& data, - const std::string& compare, - bool value) -{ - // - // this method is a little goofy, because it gets the stream at - // the point where the t or f has already been - // consumed. Basically, parse for a patch to the string passed in - // starting at index 1. If it's a match: - // * assign data to value - // * return the number of bytes read - // otherwise: - // * set data to LLSD::null - // * return LLSDParser::PARSE_FAILURE (-1) - // - int bytes_read = 0; - std::string::size_type ii = 0; - char c = istr.peek(); - while((++ii < compare.size()) - && (tolower(c) == (int)compare[ii]) - && istr.good()) - { - istr.ignore(); - ++bytes_read; - c = istr.peek(); - } - if(compare.size() != ii) - { - data.clear(); - return LLSDParser::PARSE_FAILURE; - } - data = value; - return bytes_read; -} - -std::ostream& operator<<(std::ostream& s, const LLSD& llsd) -{ - s << LLSDNotationStreamer(llsd); - return s; -} - - -//dirty little zippers -- yell at davep if these are horrid - -//return a string containing gzipped bytes of binary serialized LLSD -// VERY inefficient -- creates several copies of LLSD block in memory -std::string zip_llsd(LLSD& data) -{ - std::stringstream llsd_strm; - - LLSDSerialize::toBinary(data, llsd_strm); - - const U32 CHUNK = 65536; - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); - if (ret != Z_OK) - { - llwarns << "Failed to compress LLSD block." << llendl; - return std::string(); - } - - std::string source = llsd_strm.str(); - - U8 out[CHUNK]; - - strm.avail_in = source.size(); - strm.next_in = (U8*) source.data(); - U8* output = NULL; - - U32 cur_size = 0; - - U32 have = 0; - - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - - ret = deflate(&strm, Z_FINISH); - if (ret == Z_OK || ret == Z_STREAM_END) - { //copy result into output - if (strm.avail_out >= CHUNK) - { - free(output); - llwarns << "Failed to compress LLSD block." << llendl; - return std::string(); - } - - have = CHUNK-strm.avail_out; - output = (U8*) realloc(output, cur_size+have); - memcpy(output+cur_size, out, have); - cur_size += have; - } - else - { - free(output); - llwarns << "Failed to compress LLSD block." << llendl; - return std::string(); - } - } - while (ret == Z_OK); - - std::string::size_type size = cur_size; - - std::string result((char*) output, size); - deflateEnd(&strm); - free(output); - -#if 0 //verify results work with unzip_llsd - std::istringstream test(result); - LLSD test_sd; - if (!unzip_llsd(test_sd, test, result.size())) - { - llerrs << "Invalid compression result!" << llendl; - } -#endif - - return result; -} - -//decompress a block of LLSD from provided istream -// not very efficient -- creats a copy of decompressed LLSD block in memory -// and deserializes from that copy using LLSDSerialize -bool unzip_llsd(LLSD& data, std::istream& is, S32 size) -{ - U8* result = NULL; - U32 cur_size = 0; - z_stream strm; - - const U32 CHUNK = 65536; - - U8 *in = new U8[size]; - is.read((char*) in, size); - - U8 out[CHUNK]; - - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = size; - strm.next_in = in; - - S32 ret = inflateInit(&strm); - - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR) - { - inflateEnd(&strm); - free(result); - delete [] in; - return false; - } - - switch (ret) - { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; - case Z_DATA_ERROR: - case Z_MEM_ERROR: - inflateEnd(&strm); - free(result); - delete [] in; - return false; - break; - } - - U32 have = CHUNK-strm.avail_out; - - result = (U8*) realloc(result, cur_size + have); - memcpy(result+cur_size, out, have); - cur_size += have; - - } while (ret == Z_OK); - - inflateEnd(&strm); - delete [] in; - - if (ret != Z_STREAM_END) - { - free(result); - return false; - } - - //result now points to the decompressed LLSD block - { - std::string res_str((char*) result, cur_size); - - std::string deprecated_header(""); - - if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - { - res_str = res_str.substr(deprecated_header.size()+1, cur_size); - } - cur_size = res_str.size(); - - std::istringstream istr(res_str); - - if (!LLSDSerialize::fromBinary(data, istr, cur_size)) - { - llwarns << "Failed to unzip LLSD block" << llendl; - free(result); - return false; - } - } - - free(result); - return true; -} -//This unzip function will only work with a gzip header and trailer - while the contents -//of the actual compressed data is the same for either format (gzip vs zlib ), the headers -//and trailers are different for the formats. -U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) -{ - U8* result = NULL; - U32 cur_size = 0; - z_stream strm; - - const U32 CHUNK = 0x4000; - - U8 *in = new U8[size]; - is.read((char*) in, size); - - U8 out[CHUNK]; - - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = size; - strm.next_in = in; - - - S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR) - { - inflateEnd(&strm); - free(result); - delete [] in; - valid = false; - } - - switch (ret) - { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; - case Z_DATA_ERROR: - case Z_MEM_ERROR: - inflateEnd(&strm); - free(result); - delete [] in; - valid = false; - break; - } - - U32 have = CHUNK-strm.avail_out; - - result = (U8*) realloc(result, cur_size + have); - memcpy(result+cur_size, out, have); - cur_size += have; - - } while (ret == Z_OK); - - inflateEnd(&strm); - delete [] in; - - if (ret != Z_STREAM_END) - { - free(result); - valid = false; - return NULL; - } - - //result now points to the decompressed LLSD block - { - outsize= cur_size; - valid = true; - } - - return result; -} - - +/** + * @file llsdserialize.cpp + * @author Phoenix + * @date 2006-03-05 + * @brief Implementation of LLSD parsers and formatters + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llsdserialize.h" +#include "llpointer.h" +#include "llstreamtools.h" // for fullread + +#include +#include "apr_base64.h" + +#ifdef LL_STANDALONE +# include +#else +# include "zlib/zlib.h" // for davep's dirty little zip functions +#endif + +#if !LL_WINDOWS +#include // htonl & ntohl +#endif + +#include "lldate.h" +#include "llsd.h" +#include "llstring.h" +#include "lluri.h" + +// File constants +static const int MAX_HDR_LEN = 20; +static const char LEGACY_NON_HEADER[] = ""; +const std::string LLSD_BINARY_HEADER("LLSD/Binary"); +const std::string LLSD_XML_HEADER("LLSD/XML"); + +//used to deflate a gzipped asset (currently used for navmeshes) +#define windowBits 15 +#define ENABLE_ZLIB_GZIP 32 + +/** + * LLSDSerialize + */ + +// static +void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options) +{ + LLPointer f = NULL; + + switch (type) + { + case LLSD_BINARY: + str << "\n"; + f = new LLSDBinaryFormatter; + break; + + case LLSD_XML: + str << "\n"; + f = new LLSDXMLFormatter; + break; + + default: + llwarns << "serialize request for unknown ELLSD_Serialize" << llendl; + } + + if (f.notNull()) + { + f->format(sd, str, options); + } +} + +// static +bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) +{ + LLPointer p = NULL; + char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ + int i; + int inbuf = 0; + bool legacy_no_header = false; + bool fail_if_not_legacy = false; + std::string header; + + /* + * Get the first line before anything. + */ + str.get(hdr_buf, MAX_HDR_LEN, '\n'); + if (str.fail()) + { + str.clear(); + fail_if_not_legacy = true; + } + + if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ + { + legacy_no_header = true; + inbuf = (int)str.gcount(); + } + else + { + if (fail_if_not_legacy) + goto fail; + /* + * Remove the newline chars + */ + for (i = 0; i < MAX_HDR_LEN; i++) + { + if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' || + hdr_buf[i] == '\n') + { + hdr_buf[i] = 0; + break; + } + } + header = hdr_buf; + + std::string::size_type start = std::string::npos; + std::string::size_type end = std::string::npos; + start = header.find_first_not_of("parsePart(hdr_buf, inbuf); // Parse the first part that was already read + x->parseLines(str, sd); // Parse the rest of it + delete x; + return true; + } + + if (header == LLSD_BINARY_HEADER) + { + p = new LLSDBinaryParser; + } + else if (header == LLSD_XML_HEADER) + { + p = new LLSDXMLParser; + } + else + { + llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl; + } + + if (p.notNull()) + { + p->parse(str, sd, max_bytes); + return true; + } + +fail: + llwarns << "deserialize LLSD parse failure" << llendl; + return false; +} + +/** + * Endian handlers + */ +#if LL_BIG_ENDIAN +U64 ll_htonll(U64 hostlonglong) { return hostlonglong; } +U64 ll_ntohll(U64 netlonglong) { return netlonglong; } +F64 ll_htond(F64 hostlonglong) { return hostlonglong; } +F64 ll_ntohd(F64 netlonglong) { return netlonglong; } +#else +// I read some comments one a indicating that doing an integer add +// here would be faster than a bitwise or. For now, the or has +// programmer clarity, since the intended outcome matches the +// operation. +U64 ll_htonll(U64 hostlonglong) +{ + return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) | + ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32)); +} +U64 ll_ntohll(U64 netlonglong) +{ + return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) | + ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32)); +} +union LLEndianSwapper +{ + F64 d; + U64 i; +}; +F64 ll_htond(F64 hostdouble) +{ + LLEndianSwapper tmp; + tmp.d = hostdouble; + tmp.i = ll_htonll(tmp.i); + return tmp.d; +} +F64 ll_ntohd(F64 netdouble) +{ + LLEndianSwapper tmp; + tmp.d = netdouble; + tmp.i = ll_ntohll(tmp.i); + return tmp.d; +} +#endif + +/** + * Local functions. + */ +/** + * @brief Figure out what kind of string it is (raw or delimited) and handoff. + * + * @param istr The stream to read from. + * @param value [out] The string which was found. + * @param max_bytes The maximum possible length of the string. Passing in + * a negative value will skip this check. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes); + +/** + * @brief Parse a delimited string. + * + * @param istr The stream to read from, with the delimiter already popped. + * @param value [out] The string which was found. + * @param d The delimiter to use. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_string_delim(std::istream& istr, std::string& value, char d); + +/** + * @brief Read a raw string off the stream. + * + * @param istr The stream to read from, with the (len) parameter + * leading the stream. + * @param value [out] The string which was found. + * @param d The delimiter to use. + * @param max_bytes The maximum possible length of the string. Passing in + * a negative value will skip this check. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_string_raw( + std::istream& istr, + std::string& value, + S32 max_bytes); + +/** + * @brief helper method for dealing with the different notation boolean format. + * + * @param istr The stream to read from with the leading character stripped. + * @param data [out] the result of the parse. + * @param compare The string to compare the boolean against + * @param vale The value to assign to data if the parse succeeds. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_boolean( + std::istream& istr, + LLSD& data, + const std::string& compare, + bool value); + +/** + * @brief Do notation escaping of a string to an ostream. + * + * @param value The string to escape and serialize + * @param str The stream to serialize to. + */ +void serialize_string(const std::string& value, std::ostream& str); + + +/** + * Local constants. + */ +static const std::string NOTATION_TRUE_SERIAL("true"); +static const std::string NOTATION_FALSE_SERIAL("false"); + +static const char BINARY_TRUE_SERIAL = '1'; +static const char BINARY_FALSE_SERIAL = '0'; + + +/** + * LLSDParser + */ +LLSDParser::LLSDParser() + : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false) +{ +} + +// virtual +LLSDParser::~LLSDParser() +{ } + +S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes) +{ + mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; + mMaxBytesLeft = max_bytes; + return doParse(istr, data); +} + + +// Parse using routine to get() lines, faster than parse() +S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) +{ + mCheckLimits = false; + mParseLines = true; + return doParse(istr, data); +} + + +int LLSDParser::get(std::istream& istr) const +{ + if(mCheckLimits) --mMaxBytesLeft; + return istr.get(); +} + +std::istream& LLSDParser::get( + std::istream& istr, + char* s, + std::streamsize n, + char delim) const +{ + istr.get(s, n, delim); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); + return istr; +} + +std::istream& LLSDParser::get( + std::istream& istr, + std::streambuf& sb, + char delim) const +{ + istr.get(sb, delim); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); + return istr; +} + +std::istream& LLSDParser::ignore(std::istream& istr) const +{ + istr.ignore(); + if(mCheckLimits) --mMaxBytesLeft; + return istr; +} + +std::istream& LLSDParser::putback(std::istream& istr, char c) const +{ + istr.putback(c); + if(mCheckLimits) ++mMaxBytesLeft; + return istr; +} + +std::istream& LLSDParser::read( + std::istream& istr, + char* s, + std::streamsize n) const +{ + istr.read(s, n); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); + return istr; +} + +void LLSDParser::account(S32 bytes) const +{ + if(mCheckLimits) mMaxBytesLeft -= bytes; +} + + +/** + * LLSDNotationParser + */ +LLSDNotationParser::LLSDNotationParser() +{ +} + +// virtual +LLSDNotationParser::~LLSDNotationParser() +{ } + +// virtual +S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const +{ + // map: { string:object, string:object } + // array: [ object, object, object ] + // undef: ! + // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE + // integer: i#### + // real: r#### + // uuid: u#### + // string: "g'day" | 'have a "nice" day' | s(size)"raw data" + // uri: l"escaped" + // date: d"YYYY-MM-DDTHH:MM:SS.FFZ" + // binary: b##"ff3120ab1" | b(size)"raw data" + char c; + c = istr.peek(); + while(isspace(c)) + { + // pop the whitespace. + c = get(istr); + c = istr.peek(); + continue; + } + if(!istr.good()) + { + return 0; + } + S32 parse_count = 1; + switch(c) + { + case '{': + { + S32 child_count = parseMap(istr, data); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading map." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case '[': + { + S32 child_count = parseArray(istr, data); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading array." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case '!': + c = get(istr); + data.clear(); + break; + + case '0': + c = get(istr); + data = false; + break; + + case 'F': + case 'f': + ignore(istr); + c = istr.peek(); + if(isalpha(c)) + { + int cnt = deserialize_boolean( + istr, + data, + NOTATION_FALSE_SERIAL, + false); + if(PARSE_FAILURE == cnt) parse_count = cnt; + else account(cnt); + } + else + { + data = false; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading boolean." << llendl; + parse_count = PARSE_FAILURE; + } + break; + + case '1': + c = get(istr); + data = true; + break; + + case 'T': + case 't': + ignore(istr); + c = istr.peek(); + if(isalpha(c)) + { + int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true); + if(PARSE_FAILURE == cnt) parse_count = cnt; + else account(cnt); + } + else + { + data = true; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading boolean." << llendl; + parse_count = PARSE_FAILURE; + } + break; + + case 'i': + { + c = get(istr); + S32 integer = 0; + istr >> integer; + data = integer; + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading integer." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'r': + { + c = get(istr); + F64 real = 0.0; + istr >> real; + data = real; + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading real." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'u': + { + c = get(istr); + LLUUID id; + istr >> id; + data = id; + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading uuid." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case '\"': + case '\'': + case 's': + if(!parseString(istr, data)) + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading string." << llendl; + parse_count = PARSE_FAILURE; + } + break; + + case 'l': + { + c = get(istr); // pop the 'l' + c = get(istr); // pop the delimiter + std::string str; + int cnt = deserialize_string_delim(istr, str, c); + if(PARSE_FAILURE == cnt) + { + parse_count = PARSE_FAILURE; + } + else + { + data = LLURI(str); + account(cnt); + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading link." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'd': + { + c = get(istr); // pop the 'd' + c = get(istr); // pop the delimiter + std::string str; + int cnt = deserialize_string_delim(istr, str, c); + if(PARSE_FAILURE == cnt) + { + parse_count = PARSE_FAILURE; + } + else + { + data = LLDate(str); + account(cnt); + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading date." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'b': + if(!parseBinary(istr, data)) + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading data." << llendl; + parse_count = PARSE_FAILURE; + } + break; + + default: + parse_count = PARSE_FAILURE; + llinfos << "Unrecognized character while parsing: int(" << (int)c + << ")" << llendl; + break; + } + if(PARSE_FAILURE == parse_count) + { + data.clear(); + } + return parse_count; +} + +S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const +{ + // map: { string:object, string:object } + map = LLSD::emptyMap(); + S32 parse_count = 0; + char c = get(istr); + if(c == '{') + { + // eat commas, white + bool found_name = false; + std::string name; + c = get(istr); + while(c != '}' && istr.good()) + { + if(!found_name) + { + if((c == '\"') || (c == '\'') || (c == 's')) + { + putback(istr, c); + found_name = true; + int count = deserialize_string(istr, name, mMaxBytesLeft); + if(PARSE_FAILURE == count) return PARSE_FAILURE; + account(count); + } + c = get(istr); + } + else + { + if(isspace(c) || (c == ':')) + { + c = get(istr); + continue; + } + putback(istr, c); + LLSD child; + S32 count = doParse(istr, child); + if(count > 0) + { + // There must be a value for every key, thus + // child_count must be greater than 0. + parse_count += count; + map.insert(name, child); + } + else + { + return PARSE_FAILURE; + } + found_name = false; + c = get(istr); + } + } + if(c != '}') + { + map.clear(); + return PARSE_FAILURE; + } + } + return parse_count; +} + +S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const +{ + // array: [ object, object, object ] + array = LLSD::emptyArray(); + S32 parse_count = 0; + char c = get(istr); + if(c == '[') + { + // eat commas, white + c = get(istr); + while((c != ']') && istr.good()) + { + LLSD child; + if(isspace(c) || (c == ',')) + { + c = get(istr); + continue; + } + putback(istr, c); + S32 count = doParse(istr, child); + if(PARSE_FAILURE == count) + { + return PARSE_FAILURE; + } + else + { + parse_count += count; + array.append(child); + } + c = get(istr); + } + if(c != ']') + { + return PARSE_FAILURE; + } + } + return parse_count; +} + +bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const +{ + std::string value; + int count = deserialize_string(istr, value, mMaxBytesLeft); + if(PARSE_FAILURE == count) return false; + account(count); + data = value; + return true; +} + +bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const +{ + // binary: b##"ff3120ab1" + // or: b(len)"..." + + // I want to manually control those values here to make sure the + // parser doesn't break when someone changes a constant somewhere + // else. + const U32 BINARY_BUFFER_SIZE = 256; + const U32 STREAM_GET_COUNT = 255; + + // need to read the base out. + char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */ + get(istr, buf, STREAM_GET_COUNT, '"'); + char c = get(istr); + if(c != '"') return false; + if(0 == strncmp("b(", buf, 2)) + { + // We probably have a valid raw binary stream. determine + // the size, and read it. + S32 len = strtol(buf + 2, NULL, 0); + if(mCheckLimits && (len > mMaxBytesLeft)) return false; + std::vector value; + if(len) + { + value.resize(len); + account((int)fullread(istr, (char *)&value[0], len)); + } + c = get(istr); // strip off the trailing double-quote + data = value; + } + else if(0 == strncmp("b64", buf, 3)) + { + // *FIX: A bit inefficient, but works for now. To make the + // format better, I would need to add a hint into the + // serialization format that indicated how long it was. + std::stringstream coded_stream; + get(istr, *(coded_stream.rdbuf()), '\"'); + c = get(istr); + std::string encoded(coded_stream.str()); + S32 len = apr_base64_decode_len(encoded.c_str()); + std::vector value; + if(len) + { + value.resize(len); + len = apr_base64_decode_binary(&value[0], encoded.c_str()); + value.resize(len); + } + data = value; + } + else if(0 == strncmp("b16", buf, 3)) + { + // yay, base 16. We pop the next character which is either a + // double quote or base 16 data. If it's a double quote, we're + // done parsing. If it's not, put the data back, and read the + // stream until the next double quote. + char* read; /*Flawfinder: ignore*/ + U8 byte; + U8 byte_buffer[BINARY_BUFFER_SIZE]; + U8* write; + std::vector value; + c = get(istr); + while(c != '"') + { + putback(istr, c); + read = buf; + write = byte_buffer; + get(istr, buf, STREAM_GET_COUNT, '"'); + c = get(istr); + while(*read != '\0') /*Flawfinder: ignore*/ + { + byte = hex_as_nybble(*read++); + byte = byte << 4; + byte |= hex_as_nybble(*read++); + *write++ = byte; + } + // copy the data out of the byte buffer + value.insert(value.end(), byte_buffer, write); + } + data = value; + } + else + { + return false; + } + return true; +} + + +/** + * LLSDBinaryParser + */ +LLSDBinaryParser::LLSDBinaryParser() +{ +} + +// virtual +LLSDBinaryParser::~LLSDBinaryParser() +{ +} + +// virtual +S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const +{ +/** + * Undefined: '!'
+ * Boolean: 't' for true 'f' for false
+ * Integer: 'i' + 4 bytes network byte order
+ * Real: 'r' + 8 bytes IEEE double
+ * UUID: 'u' + 16 byte unsigned integer
+ * String: 's' + 4 byte integer size + string
+ * strings also secretly support the notation format + * Date: 'd' + 8 byte IEEE double for seconds since epoch
+ * URI: 'l' + 4 byte integer size + string uri
+ * Binary: 'b' + 4 byte integer size + binary data
+ * Array: '[' + 4 byte integer size + all values + ']'
+ * Map: '{' + 4 byte integer size every(key + value) + '}'
+ * map keys are serialized as s + 4 byte integer size + string or in the + * notation format. + */ + char c; + c = get(istr); + if(!istr.good()) + { + return 0; + } + S32 parse_count = 1; + switch(c) + { + case '{': + { + S32 child_count = parseMap(istr, data); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary map." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case '[': + { + S32 child_count = parseArray(istr, data); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary array." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case '!': + data.clear(); + break; + + case '0': + data = false; + break; + + case '1': + data = true; + break; + + case 'i': + { + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + data = (S32)ntohl(value_nbo); + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary integer." << llendl; + } + break; + } + + case 'r': + { + F64 real_nbo = 0.0; + read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/ + data = ll_ntohd(real_nbo); + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary real." << llendl; + } + break; + } + + case 'u': + { + LLUUID id; + read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/ + data = id; + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary uuid." << llendl; + } + break; + } + + case '\'': + case '"': + { + std::string value; + int cnt = deserialize_string_delim(istr, value, c); + if(PARSE_FAILURE == cnt) + { + parse_count = PARSE_FAILURE; + } + else + { + data = value; + account(cnt); + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary (notation-style) string." + << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 's': + { + std::string value; + if(parseString(istr, value)) + { + data = value; + } + else + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary string." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'l': + { + std::string value; + if(parseString(istr, value)) + { + data = LLURI(value); + } + else + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary link." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'd': + { + F64 real = 0.0; + read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/ + data = LLDate(real); + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary date." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'b': + { + // We probably have a valid raw binary stream. determine + // the size, and read it. + U32 size_nbo = 0; + read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(size_nbo); + if(mCheckLimits && (size > mMaxBytesLeft)) + { + parse_count = PARSE_FAILURE; + } + else + { + std::vector value; + if(size > 0) + { + value.resize(size); + account((int)fullread(istr, (char*)&value[0], size)); + } + data = value; + } + if(istr.fail()) + { + llinfos << "STREAM FAILURE reading binary." << llendl; + parse_count = PARSE_FAILURE; + } + break; + } + + default: + parse_count = PARSE_FAILURE; + llinfos << "Unrecognized character while parsing: int(" << (int)c + << ")" << llendl; + break; + } + if(PARSE_FAILURE == parse_count) + { + data.clear(); + } + return parse_count; +} + +S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const +{ + map = LLSD::emptyMap(); + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(value_nbo); + S32 parse_count = 0; + S32 count = 0; + char c = get(istr); + while(c != '}' && (count < size) && istr.good()) + { + std::string name; + switch(c) + { + case 'k': + if(!parseString(istr, name)) + { + return PARSE_FAILURE; + } + break; + case '\'': + case '"': + { + int cnt = deserialize_string_delim(istr, name, c); + if(PARSE_FAILURE == cnt) return PARSE_FAILURE; + account(cnt); + break; + } + } + LLSD child; + S32 child_count = doParse(istr, child); + if(child_count > 0) + { + // There must be a value for every key, thus child_count + // must be greater than 0. + parse_count += child_count; + map.insert(name, child); + } + else + { + return PARSE_FAILURE; + } + ++count; + c = get(istr); + } + if((c != '}') || (count < size)) + { + // Make sure it is correctly terminated and we parsed as many + // as were said to be there. + return PARSE_FAILURE; + } + return parse_count; +} + +S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const +{ + array = LLSD::emptyArray(); + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(value_nbo); + + // *FIX: This would be a good place to reserve some space in the + // array... + + S32 parse_count = 0; + S32 count = 0; + char c = istr.peek(); + while((c != ']') && (count < size) && istr.good()) + { + LLSD child; + S32 child_count = doParse(istr, child); + if(PARSE_FAILURE == child_count) + { + return PARSE_FAILURE; + } + if(child_count) + { + parse_count += child_count; + array.append(child); + } + ++count; + c = istr.peek(); + } + c = get(istr); + if((c != ']') || (count < size)) + { + // Make sure it is correctly terminated and we parsed as many + // as were said to be there. + return PARSE_FAILURE; + } + return parse_count; +} + +bool LLSDBinaryParser::parseString( + std::istream& istr, + std::string& value) const +{ + // *FIX: This is memory inefficient. + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(value_nbo); + if(mCheckLimits && (size > mMaxBytesLeft)) return false; + std::vector buf; + if(size) + { + buf.resize(size); + account((int)fullread(istr, &buf[0], size)); + value.assign(buf.begin(), buf.end()); + } + return true; +} + + +/** + * LLSDFormatter + */ +LLSDFormatter::LLSDFormatter() : + mBoolAlpha(false) +{ +} + +// virtual +LLSDFormatter::~LLSDFormatter() +{ } + +void LLSDFormatter::boolalpha(bool alpha) +{ + mBoolAlpha = alpha; +} + +void LLSDFormatter::realFormat(const std::string& format) +{ + mRealFormat = format; +} + +void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const +{ + std::string buffer = llformat(mRealFormat.c_str(), real); + ostr << buffer; +} + +/** + * LLSDNotationFormatter + */ +LLSDNotationFormatter::LLSDNotationFormatter() +{ +} + +// virtual +LLSDNotationFormatter::~LLSDNotationFormatter() +{ } + +// static +std::string LLSDNotationFormatter::escapeString(const std::string& in) +{ + std::ostringstream ostr; + serialize_string(in, ostr); + return ostr.str(); +} + +// virtual +S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const +{ + S32 format_count = 1; + switch(data.type()) + { + case LLSD::TypeMap: + { + ostr << "{"; + bool need_comma = false; + LLSD::map_const_iterator iter = data.beginMap(); + LLSD::map_const_iterator end = data.endMap(); + for(; iter != end; ++iter) + { + if(need_comma) ostr << ","; + need_comma = true; + ostr << '\''; + serialize_string((*iter).first, ostr); + ostr << "':"; + format_count += format((*iter).second, ostr); + } + ostr << "}"; + break; + } + + case LLSD::TypeArray: + { + ostr << "["; + bool need_comma = false; + LLSD::array_const_iterator iter = data.beginArray(); + LLSD::array_const_iterator end = data.endArray(); + for(; iter != end; ++iter) + { + if(need_comma) ostr << ","; + need_comma = true; + format_count += format(*iter, ostr); + } + ostr << "]"; + break; + } + + case LLSD::TypeUndefined: + ostr << "!"; + break; + + case LLSD::TypeBoolean: + if(mBoolAlpha || +#if( LL_WINDOWS || __GNUC__ > 2) + (ostr.flags() & std::ios::boolalpha) +#else + (ostr.flags() & 0x0100) +#endif + ) + { + ostr << (data.asBoolean() + ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); + } + else + { + ostr << (data.asBoolean() ? 1 : 0); + } + break; + + case LLSD::TypeInteger: + ostr << "i" << data.asInteger(); + break; + + case LLSD::TypeReal: + ostr << "r"; + if(mRealFormat.empty()) + { + ostr << data.asReal(); + } + else + { + formatReal(data.asReal(), ostr); + } + break; + + case LLSD::TypeUUID: + ostr << "u" << data.asUUID(); + break; + + case LLSD::TypeString: + ostr << '\''; + serialize_string(data.asString(), ostr); + ostr << '\''; + break; + + case LLSD::TypeDate: + ostr << "d\"" << data.asDate() << "\""; + break; + + case LLSD::TypeURI: + ostr << "l\""; + serialize_string(data.asString(), ostr); + ostr << "\""; + break; + + case LLSD::TypeBinary: + { + // *FIX: memory inefficient. + std::vector buffer = data.asBinary(); + ostr << "b(" << buffer.size() << ")\""; + if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); + ostr << "\""; + break; + } + + default: + // *NOTE: This should never happen. + ostr << "!"; + break; + } + return format_count; +} + + +/** + * LLSDBinaryFormatter + */ +LLSDBinaryFormatter::LLSDBinaryFormatter() +{ +} + +// virtual +LLSDBinaryFormatter::~LLSDBinaryFormatter() +{ } + +// virtual +S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const +{ + S32 format_count = 1; + switch(data.type()) + { + case LLSD::TypeMap: + { + ostr.put('{'); + U32 size_nbo = htonl(data.size()); + ostr.write((const char*)(&size_nbo), sizeof(U32)); + LLSD::map_const_iterator iter = data.beginMap(); + LLSD::map_const_iterator end = data.endMap(); + for(; iter != end; ++iter) + { + ostr.put('k'); + formatString((*iter).first, ostr); + format_count += format((*iter).second, ostr); + } + ostr.put('}'); + break; + } + + case LLSD::TypeArray: + { + ostr.put('['); + U32 size_nbo = htonl(data.size()); + ostr.write((const char*)(&size_nbo), sizeof(U32)); + LLSD::array_const_iterator iter = data.beginArray(); + LLSD::array_const_iterator end = data.endArray(); + for(; iter != end; ++iter) + { + format_count += format(*iter, ostr); + } + ostr.put(']'); + break; + } + + case LLSD::TypeUndefined: + ostr.put('!'); + break; + + case LLSD::TypeBoolean: + if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL); + else ostr.put(BINARY_FALSE_SERIAL); + break; + + case LLSD::TypeInteger: + { + ostr.put('i'); + U32 value_nbo = htonl(data.asInteger()); + ostr.write((const char*)(&value_nbo), sizeof(U32)); + break; + } + + case LLSD::TypeReal: + { + ostr.put('r'); + F64 value_nbo = ll_htond(data.asReal()); + ostr.write((const char*)(&value_nbo), sizeof(F64)); + break; + } + + case LLSD::TypeUUID: + ostr.put('u'); + ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES); + break; + + case LLSD::TypeString: + ostr.put('s'); + formatString(data.asString(), ostr); + break; + + case LLSD::TypeDate: + { + ostr.put('d'); + F64 value = data.asReal(); + ostr.write((const char*)(&value), sizeof(F64)); + break; + } + + case LLSD::TypeURI: + ostr.put('l'); + formatString(data.asString(), ostr); + break; + + case LLSD::TypeBinary: + { + // *FIX: memory inefficient. + ostr.put('b'); + std::vector buffer = data.asBinary(); + U32 size_nbo = htonl(buffer.size()); + ostr.write((const char*)(&size_nbo), sizeof(U32)); + if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); + break; + } + + default: + // *NOTE: This should never happen. + ostr.put('!'); + break; + } + return format_count; +} + +void LLSDBinaryFormatter::formatString( + const std::string& string, + std::ostream& ostr) const +{ + U32 size_nbo = htonl(string.size()); + ostr.write((const char*)(&size_nbo), sizeof(U32)); + ostr.write(string.c_str(), string.size()); +} + +/** + * local functions + */ +int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes) +{ + int c = istr.get(); + if(istr.fail()) + { + // No data in stream, bail out but mention the character we + // grabbed. + return LLSDParser::PARSE_FAILURE; + } + + int rv = LLSDParser::PARSE_FAILURE; + switch(c) + { + case '\'': + case '"': + rv = deserialize_string_delim(istr, value, c); + break; + case 's': + // technically, less than max_bytes, but this is just meant to + // catch egregious protocol errors. parse errors will be + // caught in the case of incorrect counts. + rv = deserialize_string_raw(istr, value, max_bytes); + break; + default: + break; + } + if(LLSDParser::PARSE_FAILURE == rv) return rv; + return rv + 1; // account for the character grabbed at the top. +} + +int deserialize_string_delim( + std::istream& istr, + std::string& value, + char delim) +{ + std::ostringstream write_buffer; + bool found_escape = false; + bool found_hex = false; + bool found_digit = false; + U8 byte = 0; + int count = 0; + + while (true) + { + int next_byte = istr.get(); + ++count; + + if(istr.fail()) + { + // If our stream is empty, break out + value = write_buffer.str(); + return LLSDParser::PARSE_FAILURE; + } + + char next_char = (char)next_byte; // Now that we know it's not EOF + + if(found_escape) + { + // next character(s) is a special sequence. + if(found_hex) + { + if(found_digit) + { + found_digit = false; + found_hex = false; + found_escape = false; + byte = byte << 4; + byte |= hex_as_nybble(next_char); + write_buffer << byte; + byte = 0; + } + else + { + // next character is the first nybble of + // + found_digit = true; + byte = hex_as_nybble(next_char); + } + } + else if(next_char == 'x') + { + found_hex = true; + } + else + { + switch(next_char) + { + case 'a': + write_buffer << '\a'; + break; + case 'b': + write_buffer << '\b'; + break; + case 'f': + write_buffer << '\f'; + break; + case 'n': + write_buffer << '\n'; + break; + case 'r': + write_buffer << '\r'; + break; + case 't': + write_buffer << '\t'; + break; + case 'v': + write_buffer << '\v'; + break; + default: + write_buffer << next_char; + break; + } + found_escape = false; + } + } + else if(next_char == '\\') + { + found_escape = true; + } + else if(next_char == delim) + { + break; + } + else + { + write_buffer << next_char; + } + } + + value = write_buffer.str(); + return count; +} + +int deserialize_string_raw( + std::istream& istr, + std::string& value, + S32 max_bytes) +{ + int count = 0; + const S32 BUF_LEN = 20; + char buf[BUF_LEN]; /* Flawfinder: ignore */ + istr.get(buf, BUF_LEN - 1, ')'); + count += (int)istr.gcount(); + int c = istr.get(); + c = istr.get(); + count += 2; + if(((c == '"') || (c == '\'')) && (buf[0] == '(')) + { + // We probably have a valid raw string. determine + // the size, and read it. + // *FIX: This is memory inefficient. + S32 len = strtol(buf + 1, NULL, 0); + if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; + std::vector buf; + if(len) + { + buf.resize(len); + count += (int)fullread(istr, (char *)&buf[0], len); + value.assign(buf.begin(), buf.end()); + } + c = istr.get(); + ++count; + if(!((c == '"') || (c == '\''))) + { + return LLSDParser::PARSE_FAILURE; + } + } + else + { + return LLSDParser::PARSE_FAILURE; + } + return count; +} + +static const char* NOTATION_STRING_CHARACTERS[256] = +{ + "\\x00", // 0 + "\\x01", // 1 + "\\x02", // 2 + "\\x03", // 3 + "\\x04", // 4 + "\\x05", // 5 + "\\x06", // 6 + "\\a", // 7 + "\\b", // 8 + "\\t", // 9 + "\\n", // 10 + "\\v", // 11 + "\\f", // 12 + "\\r", // 13 + "\\x0e", // 14 + "\\x0f", // 15 + "\\x10", // 16 + "\\x11", // 17 + "\\x12", // 18 + "\\x13", // 19 + "\\x14", // 20 + "\\x15", // 21 + "\\x16", // 22 + "\\x17", // 23 + "\\x18", // 24 + "\\x19", // 25 + "\\x1a", // 26 + "\\x1b", // 27 + "\\x1c", // 28 + "\\x1d", // 29 + "\\x1e", // 30 + "\\x1f", // 31 + " ", // 32 + "!", // 33 + "\"", // 34 + "#", // 35 + "$", // 36 + "%", // 37 + "&", // 38 + "\\'", // 39 + "(", // 40 + ")", // 41 + "*", // 42 + "+", // 43 + ",", // 44 + "-", // 45 + ".", // 46 + "/", // 47 + "0", // 48 + "1", // 49 + "2", // 50 + "3", // 51 + "4", // 52 + "5", // 53 + "6", // 54 + "7", // 55 + "8", // 56 + "9", // 57 + ":", // 58 + ";", // 59 + "<", // 60 + "=", // 61 + ">", // 62 + "?", // 63 + "@", // 64 + "A", // 65 + "B", // 66 + "C", // 67 + "D", // 68 + "E", // 69 + "F", // 70 + "G", // 71 + "H", // 72 + "I", // 73 + "J", // 74 + "K", // 75 + "L", // 76 + "M", // 77 + "N", // 78 + "O", // 79 + "P", // 80 + "Q", // 81 + "R", // 82 + "S", // 83 + "T", // 84 + "U", // 85 + "V", // 86 + "W", // 87 + "X", // 88 + "Y", // 89 + "Z", // 90 + "[", // 91 + "\\\\", // 92 + "]", // 93 + "^", // 94 + "_", // 95 + "`", // 96 + "a", // 97 + "b", // 98 + "c", // 99 + "d", // 100 + "e", // 101 + "f", // 102 + "g", // 103 + "h", // 104 + "i", // 105 + "j", // 106 + "k", // 107 + "l", // 108 + "m", // 109 + "n", // 110 + "o", // 111 + "p", // 112 + "q", // 113 + "r", // 114 + "s", // 115 + "t", // 116 + "u", // 117 + "v", // 118 + "w", // 119 + "x", // 120 + "y", // 121 + "z", // 122 + "{", // 123 + "|", // 124 + "}", // 125 + "~", // 126 + "\\x7f", // 127 + "\\x80", // 128 + "\\x81", // 129 + "\\x82", // 130 + "\\x83", // 131 + "\\x84", // 132 + "\\x85", // 133 + "\\x86", // 134 + "\\x87", // 135 + "\\x88", // 136 + "\\x89", // 137 + "\\x8a", // 138 + "\\x8b", // 139 + "\\x8c", // 140 + "\\x8d", // 141 + "\\x8e", // 142 + "\\x8f", // 143 + "\\x90", // 144 + "\\x91", // 145 + "\\x92", // 146 + "\\x93", // 147 + "\\x94", // 148 + "\\x95", // 149 + "\\x96", // 150 + "\\x97", // 151 + "\\x98", // 152 + "\\x99", // 153 + "\\x9a", // 154 + "\\x9b", // 155 + "\\x9c", // 156 + "\\x9d", // 157 + "\\x9e", // 158 + "\\x9f", // 159 + "\\xa0", // 160 + "\\xa1", // 161 + "\\xa2", // 162 + "\\xa3", // 163 + "\\xa4", // 164 + "\\xa5", // 165 + "\\xa6", // 166 + "\\xa7", // 167 + "\\xa8", // 168 + "\\xa9", // 169 + "\\xaa", // 170 + "\\xab", // 171 + "\\xac", // 172 + "\\xad", // 173 + "\\xae", // 174 + "\\xaf", // 175 + "\\xb0", // 176 + "\\xb1", // 177 + "\\xb2", // 178 + "\\xb3", // 179 + "\\xb4", // 180 + "\\xb5", // 181 + "\\xb6", // 182 + "\\xb7", // 183 + "\\xb8", // 184 + "\\xb9", // 185 + "\\xba", // 186 + "\\xbb", // 187 + "\\xbc", // 188 + "\\xbd", // 189 + "\\xbe", // 190 + "\\xbf", // 191 + "\\xc0", // 192 + "\\xc1", // 193 + "\\xc2", // 194 + "\\xc3", // 195 + "\\xc4", // 196 + "\\xc5", // 197 + "\\xc6", // 198 + "\\xc7", // 199 + "\\xc8", // 200 + "\\xc9", // 201 + "\\xca", // 202 + "\\xcb", // 203 + "\\xcc", // 204 + "\\xcd", // 205 + "\\xce", // 206 + "\\xcf", // 207 + "\\xd0", // 208 + "\\xd1", // 209 + "\\xd2", // 210 + "\\xd3", // 211 + "\\xd4", // 212 + "\\xd5", // 213 + "\\xd6", // 214 + "\\xd7", // 215 + "\\xd8", // 216 + "\\xd9", // 217 + "\\xda", // 218 + "\\xdb", // 219 + "\\xdc", // 220 + "\\xdd", // 221 + "\\xde", // 222 + "\\xdf", // 223 + "\\xe0", // 224 + "\\xe1", // 225 + "\\xe2", // 226 + "\\xe3", // 227 + "\\xe4", // 228 + "\\xe5", // 229 + "\\xe6", // 230 + "\\xe7", // 231 + "\\xe8", // 232 + "\\xe9", // 233 + "\\xea", // 234 + "\\xeb", // 235 + "\\xec", // 236 + "\\xed", // 237 + "\\xee", // 238 + "\\xef", // 239 + "\\xf0", // 240 + "\\xf1", // 241 + "\\xf2", // 242 + "\\xf3", // 243 + "\\xf4", // 244 + "\\xf5", // 245 + "\\xf6", // 246 + "\\xf7", // 247 + "\\xf8", // 248 + "\\xf9", // 249 + "\\xfa", // 250 + "\\xfb", // 251 + "\\xfc", // 252 + "\\xfd", // 253 + "\\xfe", // 254 + "\\xff" // 255 +}; + +void serialize_string(const std::string& value, std::ostream& str) +{ + std::string::const_iterator it = value.begin(); + std::string::const_iterator end = value.end(); + U8 c; + for(; it != end; ++it) + { + c = (U8)(*it); + str << NOTATION_STRING_CHARACTERS[c]; + } +} + +int deserialize_boolean( + std::istream& istr, + LLSD& data, + const std::string& compare, + bool value) +{ + // + // this method is a little goofy, because it gets the stream at + // the point where the t or f has already been + // consumed. Basically, parse for a patch to the string passed in + // starting at index 1. If it's a match: + // * assign data to value + // * return the number of bytes read + // otherwise: + // * set data to LLSD::null + // * return LLSDParser::PARSE_FAILURE (-1) + // + int bytes_read = 0; + std::string::size_type ii = 0; + char c = istr.peek(); + while((++ii < compare.size()) + && (tolower(c) == (int)compare[ii]) + && istr.good()) + { + istr.ignore(); + ++bytes_read; + c = istr.peek(); + } + if(compare.size() != ii) + { + data.clear(); + return LLSDParser::PARSE_FAILURE; + } + data = value; + return bytes_read; +} + +std::ostream& operator<<(std::ostream& s, const LLSD& llsd) +{ + s << LLSDNotationStreamer(llsd); + return s; +} + + +//dirty little zippers -- yell at davep if these are horrid + +//return a string containing gzipped bytes of binary serialized LLSD +// VERY inefficient -- creates several copies of LLSD block in memory +std::string zip_llsd(LLSD& data) +{ + std::stringstream llsd_strm; + + LLSDSerialize::toBinary(data, llsd_strm); + + const U32 CHUNK = 65536; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); + if (ret != Z_OK) + { + llwarns << "Failed to compress LLSD block." << llendl; + return std::string(); + } + + std::string source = llsd_strm.str(); + + U8 out[CHUNK]; + + strm.avail_in = source.size(); + strm.next_in = (U8*) source.data(); + U8* output = NULL; + + U32 cur_size = 0; + + U32 have = 0; + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + + ret = deflate(&strm, Z_FINISH); + if (ret == Z_OK || ret == Z_STREAM_END) + { //copy result into output + if (strm.avail_out >= CHUNK) + { + free(output); + llwarns << "Failed to compress LLSD block." << llendl; + return std::string(); + } + + have = CHUNK-strm.avail_out; + output = (U8*) realloc(output, cur_size+have); + memcpy(output+cur_size, out, have); + cur_size += have; + } + else + { + free(output); + llwarns << "Failed to compress LLSD block." << llendl; + return std::string(); + } + } + while (ret == Z_OK); + + std::string::size_type size = cur_size; + + std::string result((char*) output, size); + deflateEnd(&strm); + free(output); + +#if 0 //verify results work with unzip_llsd + std::istringstream test(result); + LLSD test_sd; + if (!unzip_llsd(test_sd, test, result.size())) + { + llerrs << "Invalid compression result!" << llendl; + } +#endif + + return result; +} + +//decompress a block of LLSD from provided istream +// not very efficient -- creats a copy of decompressed LLSD block in memory +// and deserializes from that copy using LLSDSerialize +bool unzip_llsd(LLSD& data, std::istream& is, S32 size) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 65536; + + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + S32 ret = inflateInit(&strm); + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + return false; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + return false; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + return false; + } + + //result now points to the decompressed LLSD block + { + std::string res_str((char*) result, cur_size); + + std::string deprecated_header(""); + + if (res_str.substr(0, deprecated_header.size()) == deprecated_header) + { + res_str = res_str.substr(deprecated_header.size()+1, cur_size); + } + cur_size = res_str.size(); + + std::istringstream istr(res_str); + + if (!LLSDSerialize::fromBinary(data, istr, cur_size)) + { + llwarns << "Failed to unzip LLSD block" << llendl; + free(result); + return false; + } + } + + free(result); + return true; +} +//This unzip function will only work with a gzip header and trailer - while the contents +//of the actual compressed data is the same for either format (gzip vs zlib ), the headers +//and trailers are different for the formats. +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 0x4000; + + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + + S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + valid = false; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + valid = false; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + valid = false; + return NULL; + } + + //result now points to the decompressed LLSD block + { + outsize= cur_size; + valid = true; + } + + return result; +} + + diff --git a/indra/llprimitive/object_flags.h b/indra/llprimitive/object_flags.h index f7f6841b53..b06a5ad4e3 100644 --- a/indra/llprimitive/object_flags.h +++ b/indra/llprimitive/object_flags.h @@ -1,75 +1,75 @@ -/** - * @file object_flags.h - * @brief Flags for object creation and transmission - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_OBJECT_FLAGS_H -#define LL_OBJECT_FLAGS_H - -// downstream flags from sim->viewer -const U32 FLAGS_USE_PHYSICS = (1U << 0); -const U32 FLAGS_CREATE_SELECTED = (1U << 1); -const U32 FLAGS_OBJECT_MODIFY = (1U << 2); -const U32 FLAGS_OBJECT_COPY = (1U << 3); -const U32 FLAGS_OBJECT_ANY_OWNER = (1U << 4); -const U32 FLAGS_OBJECT_YOU_OWNER = (1U << 5); -const U32 FLAGS_SCRIPTED = (1U << 6); -const U32 FLAGS_HANDLE_TOUCH = (1U << 7); -const U32 FLAGS_OBJECT_MOVE = (1U << 8); -const U32 FLAGS_TAKES_MONEY = (1U << 9); -const U32 FLAGS_PHANTOM = (1U << 10); -const U32 FLAGS_INVENTORY_EMPTY = (1U << 11); -const U32 FLAGS_OBJECT_PERMANENT = (1U << 12); -const U32 FLAGS_CHARACTER = (1U << 13); -//const U32 FLAGS_UNUSED_000 = (1U << 14); // was FLAGS_JOINT_LP2P -const U32 FLAGS_INCLUDE_IN_SEARCH = (1U << 15); -const U32 FLAGS_ALLOW_INVENTORY_DROP = (1U << 16); -const U32 FLAGS_OBJECT_TRANSFER = (1U << 17); -const U32 FLAGS_OBJECT_GROUP_OWNED = (1U << 18); -//const U32 FLAGS_UNUSED_001 = (1U << 19); // was FLAGS_OBJECT_YOU_OFFICER -const U32 FLAGS_CAMERA_DECOUPLED = (1U << 20); -const U32 FLAGS_ANIM_SOURCE = (1U << 21); -const U32 FLAGS_CAMERA_SOURCE = (1U << 22); -//const U32 FLAGS_UNUSED_002 = (1U << 23); // was FLAGS_CAST_SHADOWS -//const U32 FLAGS_UNUSED_003 = (1U << 24); -//const U32 FLAGS_UNUSED_004 = (1U << 25); -//const U32 FLAGS_UNUSED_005 = (1U << 26); -//const U32 FLAGS_UNUSED_006 = (1U << 27); -const U32 FLAGS_OBJECT_OWNER_MODIFY = (1U << 28); -const U32 FLAGS_TEMPORARY_ON_REZ = (1U << 29); -//const U32 FLAGS_UNUSED_007 = (1U << 30); // was FLAGS_TEMPORARY -//const U32 FLAGS_UNUSED_008 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED -const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; - -typedef enum e_havok_joint_type -{ - HJT_INVALID = 0, - HJT_HINGE = 1, - HJT_POINT = 2, -// HJT_LPOINT = 3, -// HJT_WHEEL = 4, - HJT_EOF = 3 -} EHavokJointType; - -#endif +/** + * @file object_flags.h + * @brief Flags for object creation and transmission + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_OBJECT_FLAGS_H +#define LL_OBJECT_FLAGS_H + +// downstream flags from sim->viewer +const U32 FLAGS_USE_PHYSICS = (1U << 0); +const U32 FLAGS_CREATE_SELECTED = (1U << 1); +const U32 FLAGS_OBJECT_MODIFY = (1U << 2); +const U32 FLAGS_OBJECT_COPY = (1U << 3); +const U32 FLAGS_OBJECT_ANY_OWNER = (1U << 4); +const U32 FLAGS_OBJECT_YOU_OWNER = (1U << 5); +const U32 FLAGS_SCRIPTED = (1U << 6); +const U32 FLAGS_HANDLE_TOUCH = (1U << 7); +const U32 FLAGS_OBJECT_MOVE = (1U << 8); +const U32 FLAGS_TAKES_MONEY = (1U << 9); +const U32 FLAGS_PHANTOM = (1U << 10); +const U32 FLAGS_INVENTORY_EMPTY = (1U << 11); +const U32 FLAGS_OBJECT_PERMANENT = (1U << 12); +const U32 FLAGS_CHARACTER = (1U << 13); +//const U32 FLAGS_UNUSED_000 = (1U << 14); // was FLAGS_JOINT_LP2P +const U32 FLAGS_INCLUDE_IN_SEARCH = (1U << 15); +const U32 FLAGS_ALLOW_INVENTORY_DROP = (1U << 16); +const U32 FLAGS_OBJECT_TRANSFER = (1U << 17); +const U32 FLAGS_OBJECT_GROUP_OWNED = (1U << 18); +//const U32 FLAGS_UNUSED_001 = (1U << 19); // was FLAGS_OBJECT_YOU_OFFICER +const U32 FLAGS_CAMERA_DECOUPLED = (1U << 20); +const U32 FLAGS_ANIM_SOURCE = (1U << 21); +const U32 FLAGS_CAMERA_SOURCE = (1U << 22); +//const U32 FLAGS_UNUSED_002 = (1U << 23); // was FLAGS_CAST_SHADOWS +//const U32 FLAGS_UNUSED_003 = (1U << 24); +//const U32 FLAGS_UNUSED_004 = (1U << 25); +//const U32 FLAGS_UNUSED_005 = (1U << 26); +//const U32 FLAGS_UNUSED_006 = (1U << 27); +const U32 FLAGS_OBJECT_OWNER_MODIFY = (1U << 28); +const U32 FLAGS_TEMPORARY_ON_REZ = (1U << 29); +//const U32 FLAGS_UNUSED_007 = (1U << 30); // was FLAGS_TEMPORARY +//const U32 FLAGS_UNUSED_008 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED +const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; + +typedef enum e_havok_joint_type +{ + HJT_INVALID = 0, + HJT_HINGE = 1, + HJT_POINT = 2, +// HJT_LPOINT = 3, +// HJT_WHEEL = 4, + HJT_EOF = 3 +} EHavokJointType; + +#endif diff --git a/indra/newview/llfloaterpathfindingbasic.cpp b/indra/newview/llfloaterpathfindingbasic.cpp index 19d6742559..40752352ea 100644 --- a/indra/newview/llfloaterpathfindingbasic.cpp +++ b/indra/newview/llfloaterpathfindingbasic.cpp @@ -1,167 +1,167 @@ -/** -* @file llfloaterpathfindingbasic.cpp -* @author William Todd Stinson -* @brief "Pathfinding basic" floater, allowing for basic freezing and unfreezing of the pathfinding avatar mode. -* -* $LicenseInfo:firstyear=2002&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" -#include "llfloaterpathfindingbasic.h" -#include "llsd.h" -#include "lltextbase.h" -#include "llbutton.h" -#include "llpathfindingmanager.h" - -#include - -//--------------------------------------------------------------------------- -// LLFloaterPathfindingBasic -//--------------------------------------------------------------------------- - -BOOL LLFloaterPathfindingBasic::postBuild() -{ - mStatusText = findChild("status_label"); - llassert(mStatusText != NULL); - - mUnfreezeLabel = findChild("unfreeze_label"); - llassert(mUnfreezeLabel != NULL); - - mUnfreezeButton = findChild("enter_unfrozen_mode"); - llassert(mUnfreezeButton != NULL); - mUnfreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onUnfreezeClicked, this)); - - mFreezeLabel = findChild("freeze_label"); - llassert(mFreezeLabel != NULL); - - mFreezeButton = findChild("enter_frozen_mode"); - llassert(mFreezeButton != NULL); - mFreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onFreezeClicked, this)); - - return LLFloater::postBuild(); -} - -void LLFloaterPathfindingBasic::onOpen(const LLSD& pKey) -{ - LLFloater::onOpen(pKey); - - if (!mAgentStateSlot.connected()) - { - mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1)); - } - setAgentState(LLPathfindingManager::getInstance()->getAgentState()); -} - -void LLFloaterPathfindingBasic::onClose(bool pIsAppQuitting) -{ - if (mAgentStateSlot.connected()) - { - mAgentStateSlot.disconnect(); - } - - LLFloater::onClose(pIsAppQuitting); -} - -LLFloaterPathfindingBasic::LLFloaterPathfindingBasic(const LLSD& pSeed) - : LLFloater(pSeed), - mStatusText(NULL), - mUnfreezeLabel(NULL), - mUnfreezeButton(NULL), - mFreezeLabel(NULL), - mFreezeButton(NULL), - mAgentStateSlot() -{ -} - -LLFloaterPathfindingBasic::~LLFloaterPathfindingBasic() -{ -} - -void LLFloaterPathfindingBasic::onUnfreezeClicked() -{ - mUnfreezeButton->setEnabled(FALSE); - LLPathfindingManager::getInstance()->requestSetAgentState(LLPathfindingManager::kAgentStateUnfrozen); -} - -void LLFloaterPathfindingBasic::onFreezeClicked() -{ - mUnfreezeButton->setEnabled(FALSE); - LLPathfindingManager::getInstance()->requestSetAgentState(LLPathfindingManager::kAgentStateFrozen); -} - -void LLFloaterPathfindingBasic::onAgentStateCB(LLPathfindingManager::EAgentState pAgentState) -{ - setAgentState(pAgentState); -} - -void LLFloaterPathfindingBasic::setAgentState(LLPathfindingManager::EAgentState pAgentState) -{ - static const LLColor4 errorColor = LLUIColorTable::instance().getColor("PathfindingErrorColor"); - LLStyle::Params styleParams; - - switch (pAgentState) - { - case LLPathfindingManager::kAgentStateUnknown : - mStatusText->setVisible(TRUE); - mStatusText->setText((LLStringExplicit)getString("status_querying_state"), styleParams); - break; - case LLPathfindingManager::kAgentStateNotEnabled : - mStatusText->setVisible(TRUE); - styleParams.color = errorColor; - mStatusText->setText((LLStringExplicit)getString("status_pathfinding_not_enabled"), styleParams); - break; - case LLPathfindingManager::kAgentStateError : - mStatusText->setVisible(TRUE); - styleParams.color = errorColor; - mStatusText->setText((LLStringExplicit)getString("status_unable_to_change_state"), styleParams); - break; - default : - mStatusText->setVisible(FALSE); - break; - } - - switch (LLPathfindingManager::getInstance()->getLastKnownNonErrorAgentState()) - { - case LLPathfindingManager::kAgentStateUnknown : - case LLPathfindingManager::kAgentStateNotEnabled : - mUnfreezeLabel->setEnabled(FALSE); - mUnfreezeButton->setEnabled(FALSE); - mFreezeLabel->setEnabled(FALSE); - mFreezeButton->setEnabled(FALSE); - break; - case LLPathfindingManager::kAgentStateFrozen : - mUnfreezeLabel->setEnabled(TRUE); - mUnfreezeButton->setEnabled(TRUE); - mFreezeLabel->setEnabled(FALSE); - mFreezeButton->setEnabled(FALSE); - break; - case LLPathfindingManager::kAgentStateUnfrozen : - mUnfreezeLabel->setEnabled(FALSE); - mUnfreezeButton->setEnabled(FALSE); - mFreezeLabel->setEnabled(TRUE); - mFreezeButton->setEnabled(TRUE); - break; - default : - llassert(0); - break; - } -} +/** +* @file llfloaterpathfindingbasic.cpp +* @author William Todd Stinson +* @brief "Pathfinding basic" floater, allowing for basic freezing and unfreezing of the pathfinding avatar mode. +* +* $LicenseInfo:firstyear=2002&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterpathfindingbasic.h" +#include "llsd.h" +#include "lltextbase.h" +#include "llbutton.h" +#include "llpathfindingmanager.h" + +#include + +//--------------------------------------------------------------------------- +// LLFloaterPathfindingBasic +//--------------------------------------------------------------------------- + +BOOL LLFloaterPathfindingBasic::postBuild() +{ + mStatusText = findChild("status_label"); + llassert(mStatusText != NULL); + + mUnfreezeLabel = findChild("unfreeze_label"); + llassert(mUnfreezeLabel != NULL); + + mUnfreezeButton = findChild("enter_unfrozen_mode"); + llassert(mUnfreezeButton != NULL); + mUnfreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onUnfreezeClicked, this)); + + mFreezeLabel = findChild("freeze_label"); + llassert(mFreezeLabel != NULL); + + mFreezeButton = findChild("enter_frozen_mode"); + llassert(mFreezeButton != NULL); + mFreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onFreezeClicked, this)); + + return LLFloater::postBuild(); +} + +void LLFloaterPathfindingBasic::onOpen(const LLSD& pKey) +{ + LLFloater::onOpen(pKey); + + if (!mAgentStateSlot.connected()) + { + mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1)); + } + setAgentState(LLPathfindingManager::getInstance()->getAgentState()); +} + +void LLFloaterPathfindingBasic::onClose(bool pIsAppQuitting) +{ + if (mAgentStateSlot.connected()) + { + mAgentStateSlot.disconnect(); + } + + LLFloater::onClose(pIsAppQuitting); +} + +LLFloaterPathfindingBasic::LLFloaterPathfindingBasic(const LLSD& pSeed) + : LLFloater(pSeed), + mStatusText(NULL), + mUnfreezeLabel(NULL), + mUnfreezeButton(NULL), + mFreezeLabel(NULL), + mFreezeButton(NULL), + mAgentStateSlot() +{ +} + +LLFloaterPathfindingBasic::~LLFloaterPathfindingBasic() +{ +} + +void LLFloaterPathfindingBasic::onUnfreezeClicked() +{ + mUnfreezeButton->setEnabled(FALSE); + LLPathfindingManager::getInstance()->requestSetAgentState(LLPathfindingManager::kAgentStateUnfrozen); +} + +void LLFloaterPathfindingBasic::onFreezeClicked() +{ + mUnfreezeButton->setEnabled(FALSE); + LLPathfindingManager::getInstance()->requestSetAgentState(LLPathfindingManager::kAgentStateFrozen); +} + +void LLFloaterPathfindingBasic::onAgentStateCB(LLPathfindingManager::EAgentState pAgentState) +{ + setAgentState(pAgentState); +} + +void LLFloaterPathfindingBasic::setAgentState(LLPathfindingManager::EAgentState pAgentState) +{ + static const LLColor4 errorColor = LLUIColorTable::instance().getColor("PathfindingErrorColor"); + LLStyle::Params styleParams; + + switch (pAgentState) + { + case LLPathfindingManager::kAgentStateUnknown : + mStatusText->setVisible(TRUE); + mStatusText->setText((LLStringExplicit)getString("status_querying_state"), styleParams); + break; + case LLPathfindingManager::kAgentStateNotEnabled : + mStatusText->setVisible(TRUE); + styleParams.color = errorColor; + mStatusText->setText((LLStringExplicit)getString("status_pathfinding_not_enabled"), styleParams); + break; + case LLPathfindingManager::kAgentStateError : + mStatusText->setVisible(TRUE); + styleParams.color = errorColor; + mStatusText->setText((LLStringExplicit)getString("status_unable_to_change_state"), styleParams); + break; + default : + mStatusText->setVisible(FALSE); + break; + } + + switch (LLPathfindingManager::getInstance()->getLastKnownNonErrorAgentState()) + { + case LLPathfindingManager::kAgentStateUnknown : + case LLPathfindingManager::kAgentStateNotEnabled : + mUnfreezeLabel->setEnabled(FALSE); + mUnfreezeButton->setEnabled(FALSE); + mFreezeLabel->setEnabled(FALSE); + mFreezeButton->setEnabled(FALSE); + break; + case LLPathfindingManager::kAgentStateFrozen : + mUnfreezeLabel->setEnabled(TRUE); + mUnfreezeButton->setEnabled(TRUE); + mFreezeLabel->setEnabled(FALSE); + mFreezeButton->setEnabled(FALSE); + break; + case LLPathfindingManager::kAgentStateUnfrozen : + mUnfreezeLabel->setEnabled(FALSE); + mUnfreezeButton->setEnabled(FALSE); + mFreezeLabel->setEnabled(TRUE); + mFreezeButton->setEnabled(TRUE); + break; + default : + llassert(0); + break; + } +} diff --git a/indra/newview/llfloaterpathfindingcharacters.cpp b/indra/newview/llfloaterpathfindingcharacters.cpp index 9998d25c7d..ee97063352 100644 --- a/indra/newview/llfloaterpathfindingcharacters.cpp +++ b/indra/newview/llfloaterpathfindingcharacters.cpp @@ -1,558 +1,558 @@ -/** - * @file llfloaterpathfindingcharacters.cpp - * @author William Todd Stinson - * @brief "Pathfinding characters" floater, allowing for identification of pathfinding characters and their cpu usage. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llfloater.h" -#include "llfloaterpathfindingcharacters.h" -#include "llpathfindingcharacterlist.h" -#include "llsd.h" -#include "llagent.h" -#include "llhandle.h" -#include "llfloaterreg.h" -#include "lltextbase.h" -#include "llscrolllistitem.h" -#include "llscrolllistctrl.h" -#include "llcheckboxctrl.h" -#include "llradiogroup.h" -#include "llbutton.h" -#include "llresmgr.h" -#include "llviewerregion.h" -#include "llhttpclient.h" -#include "lluuid.h" -#include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llviewermenu.h" -#include "llselectmgr.h" -#include "llenvmanager.h" - -//--------------------------------------------------------------------------- -// LLFloaterPathfindingCharacters -//--------------------------------------------------------------------------- - -BOOL LLFloaterPathfindingCharacters::postBuild() -{ - mCharactersScrollList = findChild("pathfinding_characters"); - llassert(mCharactersScrollList != NULL); - mCharactersScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onCharactersSelectionChange, this)); - mCharactersScrollList->sortByColumnIndex(0, true); - - mCharactersStatus = findChild("characters_status"); - llassert(mCharactersStatus != NULL); - - mRefreshListButton = findChild("refresh_characters_list"); - llassert(mRefreshListButton != NULL); - mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onRefreshCharactersClicked, this)); - - mSelectAllButton = findChild("select_all_characters"); - llassert(mSelectAllButton != NULL); - mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectAllCharactersClicked, this)); - - mSelectNoneButton = findChild("select_none_characters"); - llassert(mSelectNoneButton != NULL); - mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectNoneCharactersClicked, this)); - - mShowBeaconCheckBox = findChild("show_beacon"); - llassert(mShowBeaconCheckBox != NULL); - - mTakeButton = findChild("take_characters"); - llassert(mTakeButton != NULL) - mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCharactersClicked, this)); - - mTakeCopyButton = findChild("take_copy_characters"); - llassert(mTakeCopyButton != NULL) - mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCopyCharactersClicked, this)); - - mReturnButton = findChild("return_characters"); - llassert(mReturnButton != NULL) - mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onReturnCharactersClicked, this)); - - mDeleteButton = findChild("delete_characters"); - llassert(mDeleteButton != NULL) - mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onDeleteCharactersClicked, this)); - - mTeleportButton = findChild("teleport_to_character"); - llassert(mTeleportButton != NULL) - mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTeleportCharacterToMeClicked, this)); - - return LLFloater::postBuild(); -} - -void LLFloaterPathfindingCharacters::onOpen(const LLSD& pKey) -{ - LLFloater::onOpen(pKey); - - requestGetCharacters(); - selectNoneCharacters(); - mCharactersScrollList->setCommitOnSelectionChange(true); - - if (!mSelectionUpdateSlot.connected()) - { - mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterPathfindingCharacters::updateControls, this)); - } - - if (!mRegionBoundarySlot.connected()) - { - mRegionBoundarySlot = LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterPathfindingCharacters::onRegionBoundaryCross, this)); - } -} - -void LLFloaterPathfindingCharacters::onClose(bool pAppQuitting) -{ - if (mRegionBoundarySlot.connected()) - { - mRegionBoundarySlot.disconnect(); - } - - if (mSelectionUpdateSlot.connected()) - { - mSelectionUpdateSlot.disconnect(); - } - - mCharactersScrollList->setCommitOnSelectionChange(false); - selectNoneCharacters(); - if (mCharacterSelection.notNull()) - { - mCharacterSelection.clear(); - } - - LLFloater::onClose(pAppQuitting); -} - -void LLFloaterPathfindingCharacters::draw() -{ - if (mShowBeaconCheckBox->get()) - { - std::vector selectedItems = mCharactersScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - int numSelectedItems = selectedItems.size(); - - std::vector viewerObjects; - viewerObjects.reserve(numSelectedItems); - - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - selectedItemIter != selectedItems.end(); ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - - const std::string &objectName = selectedItem->getColumn(0)->getValue().asString(); - - LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); - if (viewerObject != NULL) - { - gObjectList.addDebugBeacon(viewerObject->getPositionAgent(), objectName, LLColor4(0.f, 0.f, 1.f, 0.8f), LLColor4(1.f, 1.f, 1.f, 1.f), 6); - } - } - } - } - - LLFloater::draw(); -} - -void LLFloaterPathfindingCharacters::openCharactersViewer() -{ - LLFloaterReg::toggleInstanceOrBringToFront("pathfinding_characters"); -} - -LLFloaterPathfindingCharacters::LLFloaterPathfindingCharacters(const LLSD& pSeed) - : LLFloater(pSeed), - mCharactersScrollList(NULL), - mCharactersStatus(NULL), - mRefreshListButton(NULL), - mSelectAllButton(NULL), - mSelectNoneButton(NULL), - mShowBeaconCheckBox(NULL), - mTakeButton(NULL), - mTakeCopyButton(NULL), - mReturnButton(NULL), - mDeleteButton(NULL), - mTeleportButton(NULL), - mMessagingState(kMessagingUnknown), - mMessagingRequestId(0U), - mCharacterListPtr(), - mCharacterSelection(), - mSelectionUpdateSlot() -{ -} - -LLFloaterPathfindingCharacters::~LLFloaterPathfindingCharacters() -{ -} - -LLFloaterPathfindingCharacters::EMessagingState LLFloaterPathfindingCharacters::getMessagingState() const -{ - return mMessagingState; -} - -void LLFloaterPathfindingCharacters::setMessagingState(EMessagingState pMessagingState) -{ - mMessagingState = pMessagingState; - updateControls(); -} - -void LLFloaterPathfindingCharacters::requestGetCharacters() -{ - switch (LLPathfindingManager::getInstance()->requestGetCharacters(++mMessagingRequestId, boost::bind(&LLFloaterPathfindingCharacters::handleNewCharacters, this, _1, _2, _3))) - { - case LLPathfindingManager::kRequestStarted : - setMessagingState(kMessagingGetRequestSent); - break; - case LLPathfindingManager::kRequestCompleted : - clearCharacters(); - setMessagingState(kMessagingComplete); - break; - case LLPathfindingManager::kRequestNotEnabled : - clearCharacters(); - setMessagingState(kMessagingNotEnabled); - break; - case LLPathfindingManager::kRequestError : - setMessagingState(kMessagingGetError); - break; - default : - setMessagingState(kMessagingGetError); - llassert(0); - break; - } -} - -void LLFloaterPathfindingCharacters::handleNewCharacters(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pCharacterRequestStatus, LLPathfindingCharacterListPtr pCharacterListPtr) -{ - llassert(pRequestId <= mMessagingRequestId); - if (pRequestId == mMessagingRequestId) - { - mCharacterListPtr = pCharacterListPtr; - updateScrollList(); - - switch (pCharacterRequestStatus) - { - case LLPathfindingManager::kRequestCompleted : - setMessagingState(kMessagingComplete); - break; - case LLPathfindingManager::kRequestError : - setMessagingState(kMessagingGetError); - break; - default : - setMessagingState(kMessagingGetError); - llassert(0); - break; - } - } -} - -void LLFloaterPathfindingCharacters::onCharactersSelectionChange() -{ - mCharacterSelection.clear(); - LLSelectMgr::getInstance()->deselectAll(); - - std::vector selectedItems = mCharactersScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - int numSelectedItems = selectedItems.size(); - - std::vector viewerObjects; - viewerObjects.reserve(numSelectedItems); - - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - selectedItemIter != selectedItems.end(); ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - - LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); - if (viewerObject != NULL) - { - viewerObjects.push_back(viewerObject); - } - } - - if (!viewerObjects.empty()) - { - mCharacterSelection = LLSelectMgr::getInstance()->selectObjectAndFamily(viewerObjects); - } - } - - updateControls(); -} - -void LLFloaterPathfindingCharacters::onRefreshCharactersClicked() -{ - requestGetCharacters(); -} - -void LLFloaterPathfindingCharacters::onSelectAllCharactersClicked() -{ - selectAllCharacters(); -} - -void LLFloaterPathfindingCharacters::onSelectNoneCharactersClicked() -{ - selectNoneCharacters(); -} - -void LLFloaterPathfindingCharacters::onTakeCharactersClicked() -{ - handle_take(); -} - -void LLFloaterPathfindingCharacters::onTakeCopyCharactersClicked() -{ - handle_take_copy(); -} - -void LLFloaterPathfindingCharacters::onReturnCharactersClicked() -{ - handle_object_return(); -} - -void LLFloaterPathfindingCharacters::onDeleteCharactersClicked() -{ - handle_object_delete(); -} - -void LLFloaterPathfindingCharacters::onTeleportCharacterToMeClicked() -{ - std::vector selectedItems = mCharactersScrollList->getAllSelected(); - llassert(selectedItems.size() == 1); - if (selectedItems.size() == 1) - { - std::vector::const_reference selectedItemRef = selectedItems.front(); - const LLScrollListItem *selectedItem = selectedItemRef; - LLPathfindingCharacterList::const_iterator characterIter = mCharacterListPtr->find(selectedItem->getUUID().asString()); - const LLPathfindingCharacterPtr &characterPtr = characterIter->second; - const LLVector3 &characterLocation = characterPtr->getLocation(); - - LLViewerRegion* region = gAgent.getRegion(); - if (region != NULL) - { - gAgent.teleportRequest(region->getHandle(), characterLocation, true); - } - } -} - -void LLFloaterPathfindingCharacters::onRegionBoundaryCross() -{ - requestGetCharacters(); -} - -void LLFloaterPathfindingCharacters::selectAllCharacters() -{ - mCharactersScrollList->selectAll(); -} - -void LLFloaterPathfindingCharacters::selectNoneCharacters() -{ - mCharactersScrollList->deselectAllItems(); -} - -void LLFloaterPathfindingCharacters::clearCharacters() -{ - if (mCharacterListPtr != NULL) - { - mCharacterListPtr->clear(); - } - updateScrollList(); -} - -void LLFloaterPathfindingCharacters::updateControls() -{ - updateStatusMessage(); - updateEnableStateOnListActions(); - updateEnableStateOnEditFields(); -} - -void LLFloaterPathfindingCharacters::updateScrollList() -{ - std::vector selectedItems = mCharactersScrollList->getAllSelected(); - int numSelectedItems = selectedItems.size(); - uuid_vec_t selectedUUIDs; - if (numSelectedItems > 0) - { - selectedUUIDs.reserve(selectedItems.size()); - for (std::vector::const_iterator itemIter = selectedItems.begin(); - itemIter != selectedItems.end(); ++itemIter) - { - const LLScrollListItem *listItem = *itemIter; - selectedUUIDs.push_back(listItem->getUUID()); - } - } - - S32 origScrollPosition = mCharactersScrollList->getScrollPos(); - mCharactersScrollList->deleteAllItems(); - - if (mCharacterListPtr != NULL) - { - for (LLPathfindingCharacterList::const_iterator characterIter = mCharacterListPtr->begin(); - characterIter != mCharacterListPtr->end(); ++characterIter) - { - const LLPathfindingCharacterPtr& character(characterIter->second); - LLSD element = buildCharacterScrollListElement(character); - mCharactersScrollList->addElement(element); - } - } - - mCharactersScrollList->selectMultiple(selectedUUIDs); - mCharactersScrollList->setScrollPos(origScrollPosition); - updateControls(); -} - -LLSD LLFloaterPathfindingCharacters::buildCharacterScrollListElement(const LLPathfindingCharacterPtr pCharacterPtr) const -{ - LLSD columns; - - columns[0]["column"] = "name"; - columns[0]["value"] = pCharacterPtr->getName(); - columns[0]["font"] = "SANSSERIF"; - - columns[1]["column"] = "description"; - columns[1]["value"] = pCharacterPtr->getDescription(); - columns[1]["font"] = "SANSSERIF"; - - columns[2]["column"] = "owner"; - columns[2]["value"] = pCharacterPtr->getOwnerName(); - columns[2]["font"] = "SANSSERIF"; - - S32 cpuTime = llround(pCharacterPtr->getCPUTime()); - std::string cpuTimeString = llformat("%d", cpuTime); - LLStringUtil::format_map_t string_args; - string_args["[CPU_TIME]"] = cpuTimeString; - - columns[3]["column"] = "cpu_time"; - columns[3]["value"] = getString("character_cpu_time", string_args); - columns[3]["font"] = "SANSSERIF"; - - columns[4]["column"] = "altitude"; - columns[4]["value"] = llformat("%1.0f m", pCharacterPtr->getLocation()[2]); - columns[4]["font"] = "SANSSERIF"; - - LLSD element; - element["id"] = pCharacterPtr->getUUID().asString(); - element["column"] = columns; - - return element; -} - -void LLFloaterPathfindingCharacters::updateStatusMessage() -{ - static const LLColor4 errorColor = LLUIColorTable::instance().getColor("PathfindingErrorColor"); - static const LLColor4 warningColor = LLUIColorTable::instance().getColor("PathfindingWarningColor"); - - std::string statusText(""); - LLStyle::Params styleParams; - - switch (getMessagingState()) - { - case kMessagingUnknown: - statusText = getString("characters_messaging_initial"); - styleParams.color = errorColor; - break; - case kMessagingGetRequestSent : - statusText = getString("characters_messaging_get_inprogress"); - styleParams.color = warningColor; - break; - case kMessagingGetError : - statusText = getString("characters_messaging_get_error"); - styleParams.color = errorColor; - break; - case kMessagingComplete : - if (mCharactersScrollList->isEmpty()) - { - statusText = getString("characters_messaging_complete_none_found"); - } - else - { - S32 numItems = mCharactersScrollList->getItemCount(); - S32 numSelectedItems = mCharactersScrollList->getNumSelected(); - - LLLocale locale(LLStringUtil::getLocale()); - std::string numItemsString; - LLResMgr::getInstance()->getIntegerString(numItemsString, numItems); - - std::string numSelectedItemsString; - LLResMgr::getInstance()->getIntegerString(numSelectedItemsString, numSelectedItems); - - LLStringUtil::format_map_t string_args; - string_args["[NUM_SELECTED]"] = numSelectedItemsString; - string_args["[NUM_TOTAL]"] = numItemsString; - statusText = getString("characters_messaging_complete_available", string_args); - } - break; - case kMessagingNotEnabled: - statusText = getString("characters_messaging_not_enabled"); - styleParams.color = errorColor; - break; - default: - statusText = getString("characters_messaging_initial"); - styleParams.color = errorColor; - llassert(0); - break; - } - - mCharactersStatus->setText((LLStringExplicit)statusText, styleParams); -} - -void LLFloaterPathfindingCharacters::updateEnableStateOnListActions() -{ - switch (getMessagingState()) - { - case kMessagingUnknown: - case kMessagingGetRequestSent : - mRefreshListButton->setEnabled(FALSE); - mSelectAllButton->setEnabled(FALSE); - mSelectNoneButton->setEnabled(FALSE); - break; - case kMessagingGetError : - case kMessagingNotEnabled : - mRefreshListButton->setEnabled(TRUE); - mSelectAllButton->setEnabled(FALSE); - mSelectNoneButton->setEnabled(FALSE); - break; - case kMessagingComplete : - { - int numItems = mCharactersScrollList->getItemCount(); - int numSelectedItems = mCharactersScrollList->getNumSelected(); - mRefreshListButton->setEnabled(TRUE); - mSelectAllButton->setEnabled(numSelectedItems < numItems); - mSelectNoneButton->setEnabled(numSelectedItems > 0); - } - break; - default: - llassert(0); - break; - } -} - -void LLFloaterPathfindingCharacters::updateEnableStateOnEditFields() -{ - int numSelectedItems = mCharactersScrollList->getNumSelected(); - bool isEditEnabled = (numSelectedItems > 0); - - mShowBeaconCheckBox->setEnabled(isEditEnabled); - mTakeButton->setEnabled(isEditEnabled && visible_take_object()); - mTakeCopyButton->setEnabled(isEditEnabled && enable_object_take_copy()); - mReturnButton->setEnabled(isEditEnabled && enable_object_return()); - mDeleteButton->setEnabled(isEditEnabled && enable_object_delete()); - mTeleportButton->setEnabled(numSelectedItems == 1); -} +/** + * @file llfloaterpathfindingcharacters.cpp + * @author William Todd Stinson + * @brief "Pathfinding characters" floater, allowing for identification of pathfinding characters and their cpu usage. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloater.h" +#include "llfloaterpathfindingcharacters.h" +#include "llpathfindingcharacterlist.h" +#include "llsd.h" +#include "llagent.h" +#include "llhandle.h" +#include "llfloaterreg.h" +#include "lltextbase.h" +#include "llscrolllistitem.h" +#include "llscrolllistctrl.h" +#include "llcheckboxctrl.h" +#include "llradiogroup.h" +#include "llbutton.h" +#include "llresmgr.h" +#include "llviewerregion.h" +#include "llhttpclient.h" +#include "lluuid.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewermenu.h" +#include "llselectmgr.h" +#include "llenvmanager.h" + +//--------------------------------------------------------------------------- +// LLFloaterPathfindingCharacters +//--------------------------------------------------------------------------- + +BOOL LLFloaterPathfindingCharacters::postBuild() +{ + mCharactersScrollList = findChild("pathfinding_characters"); + llassert(mCharactersScrollList != NULL); + mCharactersScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onCharactersSelectionChange, this)); + mCharactersScrollList->sortByColumnIndex(0, true); + + mCharactersStatus = findChild("characters_status"); + llassert(mCharactersStatus != NULL); + + mRefreshListButton = findChild("refresh_characters_list"); + llassert(mRefreshListButton != NULL); + mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onRefreshCharactersClicked, this)); + + mSelectAllButton = findChild("select_all_characters"); + llassert(mSelectAllButton != NULL); + mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectAllCharactersClicked, this)); + + mSelectNoneButton = findChild("select_none_characters"); + llassert(mSelectNoneButton != NULL); + mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectNoneCharactersClicked, this)); + + mShowBeaconCheckBox = findChild("show_beacon"); + llassert(mShowBeaconCheckBox != NULL); + + mTakeButton = findChild("take_characters"); + llassert(mTakeButton != NULL) + mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCharactersClicked, this)); + + mTakeCopyButton = findChild("take_copy_characters"); + llassert(mTakeCopyButton != NULL) + mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCopyCharactersClicked, this)); + + mReturnButton = findChild("return_characters"); + llassert(mReturnButton != NULL) + mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onReturnCharactersClicked, this)); + + mDeleteButton = findChild("delete_characters"); + llassert(mDeleteButton != NULL) + mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onDeleteCharactersClicked, this)); + + mTeleportButton = findChild("teleport_to_character"); + llassert(mTeleportButton != NULL) + mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTeleportCharacterToMeClicked, this)); + + return LLFloater::postBuild(); +} + +void LLFloaterPathfindingCharacters::onOpen(const LLSD& pKey) +{ + LLFloater::onOpen(pKey); + + requestGetCharacters(); + selectNoneCharacters(); + mCharactersScrollList->setCommitOnSelectionChange(true); + + if (!mSelectionUpdateSlot.connected()) + { + mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterPathfindingCharacters::updateControls, this)); + } + + if (!mRegionBoundarySlot.connected()) + { + mRegionBoundarySlot = LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterPathfindingCharacters::onRegionBoundaryCross, this)); + } +} + +void LLFloaterPathfindingCharacters::onClose(bool pAppQuitting) +{ + if (mRegionBoundarySlot.connected()) + { + mRegionBoundarySlot.disconnect(); + } + + if (mSelectionUpdateSlot.connected()) + { + mSelectionUpdateSlot.disconnect(); + } + + mCharactersScrollList->setCommitOnSelectionChange(false); + selectNoneCharacters(); + if (mCharacterSelection.notNull()) + { + mCharacterSelection.clear(); + } + + LLFloater::onClose(pAppQuitting); +} + +void LLFloaterPathfindingCharacters::draw() +{ + if (mShowBeaconCheckBox->get()) + { + std::vector selectedItems = mCharactersScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + selectedItemIter != selectedItems.end(); ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + + const std::string &objectName = selectedItem->getColumn(0)->getValue().asString(); + + LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); + if (viewerObject != NULL) + { + gObjectList.addDebugBeacon(viewerObject->getPositionAgent(), objectName, LLColor4(0.f, 0.f, 1.f, 0.8f), LLColor4(1.f, 1.f, 1.f, 1.f), 6); + } + } + } + } + + LLFloater::draw(); +} + +void LLFloaterPathfindingCharacters::openCharactersViewer() +{ + LLFloaterReg::toggleInstanceOrBringToFront("pathfinding_characters"); +} + +LLFloaterPathfindingCharacters::LLFloaterPathfindingCharacters(const LLSD& pSeed) + : LLFloater(pSeed), + mCharactersScrollList(NULL), + mCharactersStatus(NULL), + mRefreshListButton(NULL), + mSelectAllButton(NULL), + mSelectNoneButton(NULL), + mShowBeaconCheckBox(NULL), + mTakeButton(NULL), + mTakeCopyButton(NULL), + mReturnButton(NULL), + mDeleteButton(NULL), + mTeleportButton(NULL), + mMessagingState(kMessagingUnknown), + mMessagingRequestId(0U), + mCharacterListPtr(), + mCharacterSelection(), + mSelectionUpdateSlot() +{ +} + +LLFloaterPathfindingCharacters::~LLFloaterPathfindingCharacters() +{ +} + +LLFloaterPathfindingCharacters::EMessagingState LLFloaterPathfindingCharacters::getMessagingState() const +{ + return mMessagingState; +} + +void LLFloaterPathfindingCharacters::setMessagingState(EMessagingState pMessagingState) +{ + mMessagingState = pMessagingState; + updateControls(); +} + +void LLFloaterPathfindingCharacters::requestGetCharacters() +{ + switch (LLPathfindingManager::getInstance()->requestGetCharacters(++mMessagingRequestId, boost::bind(&LLFloaterPathfindingCharacters::handleNewCharacters, this, _1, _2, _3))) + { + case LLPathfindingManager::kRequestStarted : + setMessagingState(kMessagingGetRequestSent); + break; + case LLPathfindingManager::kRequestCompleted : + clearCharacters(); + setMessagingState(kMessagingComplete); + break; + case LLPathfindingManager::kRequestNotEnabled : + clearCharacters(); + setMessagingState(kMessagingNotEnabled); + break; + case LLPathfindingManager::kRequestError : + setMessagingState(kMessagingGetError); + break; + default : + setMessagingState(kMessagingGetError); + llassert(0); + break; + } +} + +void LLFloaterPathfindingCharacters::handleNewCharacters(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pCharacterRequestStatus, LLPathfindingCharacterListPtr pCharacterListPtr) +{ + llassert(pRequestId <= mMessagingRequestId); + if (pRequestId == mMessagingRequestId) + { + mCharacterListPtr = pCharacterListPtr; + updateScrollList(); + + switch (pCharacterRequestStatus) + { + case LLPathfindingManager::kRequestCompleted : + setMessagingState(kMessagingComplete); + break; + case LLPathfindingManager::kRequestError : + setMessagingState(kMessagingGetError); + break; + default : + setMessagingState(kMessagingGetError); + llassert(0); + break; + } + } +} + +void LLFloaterPathfindingCharacters::onCharactersSelectionChange() +{ + mCharacterSelection.clear(); + LLSelectMgr::getInstance()->deselectAll(); + + std::vector selectedItems = mCharactersScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + selectedItemIter != selectedItems.end(); ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + + LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); + if (viewerObject != NULL) + { + viewerObjects.push_back(viewerObject); + } + } + + if (!viewerObjects.empty()) + { + mCharacterSelection = LLSelectMgr::getInstance()->selectObjectAndFamily(viewerObjects); + } + } + + updateControls(); +} + +void LLFloaterPathfindingCharacters::onRefreshCharactersClicked() +{ + requestGetCharacters(); +} + +void LLFloaterPathfindingCharacters::onSelectAllCharactersClicked() +{ + selectAllCharacters(); +} + +void LLFloaterPathfindingCharacters::onSelectNoneCharactersClicked() +{ + selectNoneCharacters(); +} + +void LLFloaterPathfindingCharacters::onTakeCharactersClicked() +{ + handle_take(); +} + +void LLFloaterPathfindingCharacters::onTakeCopyCharactersClicked() +{ + handle_take_copy(); +} + +void LLFloaterPathfindingCharacters::onReturnCharactersClicked() +{ + handle_object_return(); +} + +void LLFloaterPathfindingCharacters::onDeleteCharactersClicked() +{ + handle_object_delete(); +} + +void LLFloaterPathfindingCharacters::onTeleportCharacterToMeClicked() +{ + std::vector selectedItems = mCharactersScrollList->getAllSelected(); + llassert(selectedItems.size() == 1); + if (selectedItems.size() == 1) + { + std::vector::const_reference selectedItemRef = selectedItems.front(); + const LLScrollListItem *selectedItem = selectedItemRef; + LLPathfindingCharacterList::const_iterator characterIter = mCharacterListPtr->find(selectedItem->getUUID().asString()); + const LLPathfindingCharacterPtr &characterPtr = characterIter->second; + const LLVector3 &characterLocation = characterPtr->getLocation(); + + LLViewerRegion* region = gAgent.getRegion(); + if (region != NULL) + { + gAgent.teleportRequest(region->getHandle(), characterLocation, true); + } + } +} + +void LLFloaterPathfindingCharacters::onRegionBoundaryCross() +{ + requestGetCharacters(); +} + +void LLFloaterPathfindingCharacters::selectAllCharacters() +{ + mCharactersScrollList->selectAll(); +} + +void LLFloaterPathfindingCharacters::selectNoneCharacters() +{ + mCharactersScrollList->deselectAllItems(); +} + +void LLFloaterPathfindingCharacters::clearCharacters() +{ + if (mCharacterListPtr != NULL) + { + mCharacterListPtr->clear(); + } + updateScrollList(); +} + +void LLFloaterPathfindingCharacters::updateControls() +{ + updateStatusMessage(); + updateEnableStateOnListActions(); + updateEnableStateOnEditFields(); +} + +void LLFloaterPathfindingCharacters::updateScrollList() +{ + std::vector selectedItems = mCharactersScrollList->getAllSelected(); + int numSelectedItems = selectedItems.size(); + uuid_vec_t selectedUUIDs; + if (numSelectedItems > 0) + { + selectedUUIDs.reserve(selectedItems.size()); + for (std::vector::const_iterator itemIter = selectedItems.begin(); + itemIter != selectedItems.end(); ++itemIter) + { + const LLScrollListItem *listItem = *itemIter; + selectedUUIDs.push_back(listItem->getUUID()); + } + } + + S32 origScrollPosition = mCharactersScrollList->getScrollPos(); + mCharactersScrollList->deleteAllItems(); + + if (mCharacterListPtr != NULL) + { + for (LLPathfindingCharacterList::const_iterator characterIter = mCharacterListPtr->begin(); + characterIter != mCharacterListPtr->end(); ++characterIter) + { + const LLPathfindingCharacterPtr& character(characterIter->second); + LLSD element = buildCharacterScrollListElement(character); + mCharactersScrollList->addElement(element); + } + } + + mCharactersScrollList->selectMultiple(selectedUUIDs); + mCharactersScrollList->setScrollPos(origScrollPosition); + updateControls(); +} + +LLSD LLFloaterPathfindingCharacters::buildCharacterScrollListElement(const LLPathfindingCharacterPtr pCharacterPtr) const +{ + LLSD columns; + + columns[0]["column"] = "name"; + columns[0]["value"] = pCharacterPtr->getName(); + columns[0]["font"] = "SANSSERIF"; + + columns[1]["column"] = "description"; + columns[1]["value"] = pCharacterPtr->getDescription(); + columns[1]["font"] = "SANSSERIF"; + + columns[2]["column"] = "owner"; + columns[2]["value"] = pCharacterPtr->getOwnerName(); + columns[2]["font"] = "SANSSERIF"; + + S32 cpuTime = llround(pCharacterPtr->getCPUTime()); + std::string cpuTimeString = llformat("%d", cpuTime); + LLStringUtil::format_map_t string_args; + string_args["[CPU_TIME]"] = cpuTimeString; + + columns[3]["column"] = "cpu_time"; + columns[3]["value"] = getString("character_cpu_time", string_args); + columns[3]["font"] = "SANSSERIF"; + + columns[4]["column"] = "altitude"; + columns[4]["value"] = llformat("%1.0f m", pCharacterPtr->getLocation()[2]); + columns[4]["font"] = "SANSSERIF"; + + LLSD element; + element["id"] = pCharacterPtr->getUUID().asString(); + element["column"] = columns; + + return element; +} + +void LLFloaterPathfindingCharacters::updateStatusMessage() +{ + static const LLColor4 errorColor = LLUIColorTable::instance().getColor("PathfindingErrorColor"); + static const LLColor4 warningColor = LLUIColorTable::instance().getColor("PathfindingWarningColor"); + + std::string statusText(""); + LLStyle::Params styleParams; + + switch (getMessagingState()) + { + case kMessagingUnknown: + statusText = getString("characters_messaging_initial"); + styleParams.color = errorColor; + break; + case kMessagingGetRequestSent : + statusText = getString("characters_messaging_get_inprogress"); + styleParams.color = warningColor; + break; + case kMessagingGetError : + statusText = getString("characters_messaging_get_error"); + styleParams.color = errorColor; + break; + case kMessagingComplete : + if (mCharactersScrollList->isEmpty()) + { + statusText = getString("characters_messaging_complete_none_found"); + } + else + { + S32 numItems = mCharactersScrollList->getItemCount(); + S32 numSelectedItems = mCharactersScrollList->getNumSelected(); + + LLLocale locale(LLStringUtil::getLocale()); + std::string numItemsString; + LLResMgr::getInstance()->getIntegerString(numItemsString, numItems); + + std::string numSelectedItemsString; + LLResMgr::getInstance()->getIntegerString(numSelectedItemsString, numSelectedItems); + + LLStringUtil::format_map_t string_args; + string_args["[NUM_SELECTED]"] = numSelectedItemsString; + string_args["[NUM_TOTAL]"] = numItemsString; + statusText = getString("characters_messaging_complete_available", string_args); + } + break; + case kMessagingNotEnabled: + statusText = getString("characters_messaging_not_enabled"); + styleParams.color = errorColor; + break; + default: + statusText = getString("characters_messaging_initial"); + styleParams.color = errorColor; + llassert(0); + break; + } + + mCharactersStatus->setText((LLStringExplicit)statusText, styleParams); +} + +void LLFloaterPathfindingCharacters::updateEnableStateOnListActions() +{ + switch (getMessagingState()) + { + case kMessagingUnknown: + case kMessagingGetRequestSent : + mRefreshListButton->setEnabled(FALSE); + mSelectAllButton->setEnabled(FALSE); + mSelectNoneButton->setEnabled(FALSE); + break; + case kMessagingGetError : + case kMessagingNotEnabled : + mRefreshListButton->setEnabled(TRUE); + mSelectAllButton->setEnabled(FALSE); + mSelectNoneButton->setEnabled(FALSE); + break; + case kMessagingComplete : + { + int numItems = mCharactersScrollList->getItemCount(); + int numSelectedItems = mCharactersScrollList->getNumSelected(); + mRefreshListButton->setEnabled(TRUE); + mSelectAllButton->setEnabled(numSelectedItems < numItems); + mSelectNoneButton->setEnabled(numSelectedItems > 0); + } + break; + default: + llassert(0); + break; + } +} + +void LLFloaterPathfindingCharacters::updateEnableStateOnEditFields() +{ + int numSelectedItems = mCharactersScrollList->getNumSelected(); + bool isEditEnabled = (numSelectedItems > 0); + + mShowBeaconCheckBox->setEnabled(isEditEnabled); + mTakeButton->setEnabled(isEditEnabled && visible_take_object()); + mTakeCopyButton->setEnabled(isEditEnabled && enable_object_take_copy()); + mReturnButton->setEnabled(isEditEnabled && enable_object_return()); + mDeleteButton->setEnabled(isEditEnabled && enable_object_delete()); + mTeleportButton->setEnabled(numSelectedItems == 1); +} diff --git a/indra/newview/llfloaterpathfindingcharacters.h b/indra/newview/llfloaterpathfindingcharacters.h index e0f1c22eac..b7b326b885 100644 --- a/indra/newview/llfloaterpathfindingcharacters.h +++ b/indra/newview/llfloaterpathfindingcharacters.h @@ -1,128 +1,128 @@ -/** -* @file llfloaterpathfindingcharacters.h -* @author William Todd Stinson -* @brief "Pathfinding characters" floater, allowing for identification of pathfinding characters and their cpu usage. -* -* $LicenseInfo:firstyear=2002&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#ifndef LL_LLFLOATERPATHFINDINGCHARACTERS_H -#define LL_LLFLOATERPATHFINDINGCHARACTERS_H - -#include -#include - -#include "llfloater.h" -#include "llpathfindingcharacter.h" -#include "llpathfindingcharacterlist.h" -#include "llpathfindingmanager.h" -#include "llselectmgr.h" - -#include - -class LLSD; -class LLTextBase; -class LLScrollListCtrl; -class LLCheckBoxCtrl; -class LLRadioGroup; -class LLButton; - -class LLFloaterPathfindingCharacters - : public LLFloater -{ - friend class LLFloaterReg; - -public: - typedef enum - { - kMessagingUnknown, - kMessagingGetRequestSent, - kMessagingGetError, - kMessagingComplete, - kMessagingNotEnabled - } EMessagingState; - - virtual BOOL postBuild(); - virtual void onOpen(const LLSD& pKey); - virtual void onClose(bool pAppQuitting); - virtual void draw(); - - static void openCharactersViewer(); - -protected: - -private: - LLScrollListCtrl *mCharactersScrollList; - LLTextBase *mCharactersStatus; - LLButton *mRefreshListButton; - LLButton *mSelectAllButton; - LLButton *mSelectNoneButton; - LLCheckBoxCtrl *mShowBeaconCheckBox; - LLButton *mTakeButton; - LLButton *mTakeCopyButton; - LLButton *mReturnButton; - LLButton *mDeleteButton; - LLButton *mTeleportButton; - - EMessagingState mMessagingState; - LLPathfindingManager::request_id_t mMessagingRequestId; - LLPathfindingCharacterListPtr mCharacterListPtr; - LLObjectSelectionHandle mCharacterSelection; - boost::signals2::connection mSelectionUpdateSlot; - boost::signals2::connection mRegionBoundarySlot; - - // Does its own instance management, so clients not allowed - // to allocate or destroy. - LLFloaterPathfindingCharacters(const LLSD& pSeed); - virtual ~LLFloaterPathfindingCharacters(); - - EMessagingState getMessagingState() const; - void setMessagingState(EMessagingState pMessagingState); - - void requestGetCharacters(); - void handleNewCharacters(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pCharacterRequestStatus, LLPathfindingCharacterListPtr pCharacterListPtr); - - void onCharactersSelectionChange(); - void onRefreshCharactersClicked(); - void onSelectAllCharactersClicked(); - void onSelectNoneCharactersClicked(); - void onTakeCharactersClicked(); - void onTakeCopyCharactersClicked(); - void onReturnCharactersClicked(); - void onDeleteCharactersClicked(); - void onTeleportCharacterToMeClicked(); - void onRegionBoundaryCross(); - - void selectAllCharacters(); - void selectNoneCharacters(); - void clearCharacters(); - - void updateControls(); - void updateScrollList(); - LLSD buildCharacterScrollListElement(const LLPathfindingCharacterPtr pCharacterPtr) const; - - void updateStatusMessage(); - void updateEnableStateOnListActions(); - void updateEnableStateOnEditFields(); -}; - -#endif // LL_LLFLOATERPATHFINDINGCHARACTERS_H +/** +* @file llfloaterpathfindingcharacters.h +* @author William Todd Stinson +* @brief "Pathfinding characters" floater, allowing for identification of pathfinding characters and their cpu usage. +* +* $LicenseInfo:firstyear=2002&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLFLOATERPATHFINDINGCHARACTERS_H +#define LL_LLFLOATERPATHFINDINGCHARACTERS_H + +#include +#include + +#include "llfloater.h" +#include "llpathfindingcharacter.h" +#include "llpathfindingcharacterlist.h" +#include "llpathfindingmanager.h" +#include "llselectmgr.h" + +#include + +class LLSD; +class LLTextBase; +class LLScrollListCtrl; +class LLCheckBoxCtrl; +class LLRadioGroup; +class LLButton; + +class LLFloaterPathfindingCharacters + : public LLFloater +{ + friend class LLFloaterReg; + +public: + typedef enum + { + kMessagingUnknown, + kMessagingGetRequestSent, + kMessagingGetError, + kMessagingComplete, + kMessagingNotEnabled + } EMessagingState; + + virtual BOOL postBuild(); + virtual void onOpen(const LLSD& pKey); + virtual void onClose(bool pAppQuitting); + virtual void draw(); + + static void openCharactersViewer(); + +protected: + +private: + LLScrollListCtrl *mCharactersScrollList; + LLTextBase *mCharactersStatus; + LLButton *mRefreshListButton; + LLButton *mSelectAllButton; + LLButton *mSelectNoneButton; + LLCheckBoxCtrl *mShowBeaconCheckBox; + LLButton *mTakeButton; + LLButton *mTakeCopyButton; + LLButton *mReturnButton; + LLButton *mDeleteButton; + LLButton *mTeleportButton; + + EMessagingState mMessagingState; + LLPathfindingManager::request_id_t mMessagingRequestId; + LLPathfindingCharacterListPtr mCharacterListPtr; + LLObjectSelectionHandle mCharacterSelection; + boost::signals2::connection mSelectionUpdateSlot; + boost::signals2::connection mRegionBoundarySlot; + + // Does its own instance management, so clients not allowed + // to allocate or destroy. + LLFloaterPathfindingCharacters(const LLSD& pSeed); + virtual ~LLFloaterPathfindingCharacters(); + + EMessagingState getMessagingState() const; + void setMessagingState(EMessagingState pMessagingState); + + void requestGetCharacters(); + void handleNewCharacters(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pCharacterRequestStatus, LLPathfindingCharacterListPtr pCharacterListPtr); + + void onCharactersSelectionChange(); + void onRefreshCharactersClicked(); + void onSelectAllCharactersClicked(); + void onSelectNoneCharactersClicked(); + void onTakeCharactersClicked(); + void onTakeCopyCharactersClicked(); + void onReturnCharactersClicked(); + void onDeleteCharactersClicked(); + void onTeleportCharacterToMeClicked(); + void onRegionBoundaryCross(); + + void selectAllCharacters(); + void selectNoneCharacters(); + void clearCharacters(); + + void updateControls(); + void updateScrollList(); + LLSD buildCharacterScrollListElement(const LLPathfindingCharacterPtr pCharacterPtr) const; + + void updateStatusMessage(); + void updateEnableStateOnListActions(); + void updateEnableStateOnEditFields(); +}; + +#endif // LL_LLFLOATERPATHFINDINGCHARACTERS_H diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp index 9701002d7d..240b5bb741 100644 --- a/indra/newview/llfloaterpathfindinglinksets.cpp +++ b/indra/newview/llfloaterpathfindinglinksets.cpp @@ -1,1259 +1,1259 @@ -/** -* @file llfloaterpathfindinglinksets.cpp -* @author William Todd Stinson -* @brief "Pathfinding linksets" floater, allowing manipulation of the Havok AI pathfinding settings. -* -* $LicenseInfo:firstyear=2002&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" -#include "llfloater.h" -#include "llfloaterreg.h" -#include "llfloaterpathfindinglinksets.h" -#include "llsd.h" -#include "lluuid.h" -#include "v3math.h" -#include "lltextvalidate.h" -#include "llagent.h" -#include "lltextbase.h" -#include "lllineeditor.h" -#include "llscrolllistitem.h" -#include "llscrolllistctrl.h" -#include "llcombobox.h" -#include "llcheckboxctrl.h" -#include "llbutton.h" -#include "llresmgr.h" -#include "llviewerregion.h" -#include "llselectmgr.h" -#include "llviewermenu.h" -#include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llpathfindinglinkset.h" -#include "llpathfindinglinksetlist.h" -#include "llpathfindingmanager.h" -#include "llnotificationsutil.h" -#include "llenvmanager.h" - -#include -#include - -#define XUI_LINKSET_USE_NONE 0 -#define XUI_LINKSET_USE_WALKABLE 1 -#define XUI_LINKSET_USE_STATIC_OBSTACLE 2 -#define XUI_LINKSET_USE_DYNAMIC_OBSTACLE 3 -#define XUI_LINKSET_USE_MATERIAL_VOLUME 4 -#define XUI_LINKSET_USE_EXCLUSION_VOLUME 5 -#define XUI_LINKSET_USE_DYNAMIC_PHANTOM 6 - -//--------------------------------------------------------------------------- -// LLFloaterPathfindingLinksets -//--------------------------------------------------------------------------- - -BOOL LLFloaterPathfindingLinksets::postBuild() -{ - childSetAction("apply_filters", boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - childSetAction("clear_filters", boost::bind(&LLFloaterPathfindingLinksets::onClearFiltersClicked, this)); - - mFilterByName = findChild("filter_by_name"); - llassert(mFilterByName != NULL); - mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - mFilterByName->setSelectAllonFocusReceived(true); - mFilterByName->setCommitOnFocusLost(true); - - mFilterByDescription = findChild("filter_by_description"); - llassert(mFilterByDescription != NULL); - mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - mFilterByDescription->setSelectAllonFocusReceived(true); - mFilterByDescription->setCommitOnFocusLost(true); - - mFilterByLinksetUse = findChild("filter_by_linkset_use"); - llassert(mFilterByLinksetUse != NULL); - mFilterByLinksetUse->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - - mLinksetsScrollList = findChild("pathfinding_linksets"); - llassert(mLinksetsScrollList != NULL); - mLinksetsScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onLinksetsSelectionChange, this)); - mLinksetsScrollList->sortByColumnIndex(0, true); - - mLinksetsStatus = findChild("linksets_status"); - llassert(mLinksetsStatus != NULL); - - mRefreshListButton = findChild("refresh_linksets_list"); - llassert(mRefreshListButton != NULL); - mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onRefreshLinksetsClicked, this)); - - mSelectAllButton = findChild("select_all_linksets"); - llassert(mSelectAllButton != NULL); - mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectAllLinksetsClicked, this)); - - mSelectNoneButton = findChild("select_none_linksets"); - llassert(mSelectNoneButton != NULL); - mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectNoneLinksetsClicked, this)); - - mShowBeaconCheckBox = findChild("show_beacon"); - llassert(mShowBeaconCheckBox != NULL); - - mTakeButton = findChild("take_linksets"); - llassert(mTakeButton != NULL); - mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeClicked, this)); - - mTakeCopyButton = findChild("take_copy_linksets"); - llassert(mTakeCopyButton != NULL); - mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeCopyClicked, this)); - - mReturnButton = findChild("return_linksets"); - llassert(mReturnButton != NULL); - mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onReturnClicked, this)); - - mDeleteButton = findChild("delete_linksets"); - llassert(mDeleteButton != NULL); - mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onDeleteClicked, this)); - - mTeleportButton = findChild("teleport_me_to_linkset"); - llassert(mTeleportButton != NULL); - mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTeleportClicked, this)); - - mEditLinksetUse = findChild("edit_linkset_use"); - llassert(mEditLinksetUse != NULL); - - mEditLinksetUse->clearRows(); - - mEditLinksetUseUnset = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getString("linkset_choose_use"), XUI_LINKSET_USE_NONE)); - llassert(mEditLinksetUseUnset != NULL); - - mEditLinksetUseWalkable = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kWalkable), XUI_LINKSET_USE_WALKABLE)); - llassert(mEditLinksetUseWalkable != NULL); - - mEditLinksetUseStaticObstacle = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kStaticObstacle), XUI_LINKSET_USE_STATIC_OBSTACLE)); - llassert(mEditLinksetUseStaticObstacle != NULL); - - mEditLinksetUseDynamicObstacle = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kDynamicObstacle), XUI_LINKSET_USE_DYNAMIC_OBSTACLE)); - llassert(mEditLinksetUseDynamicObstacle != NULL); - - mEditLinksetUseMaterialVolume = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kMaterialVolume), XUI_LINKSET_USE_MATERIAL_VOLUME)); - llassert(mEditLinksetUseMaterialVolume != NULL); - - mEditLinksetUseExclusionVolume = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kExclusionVolume), XUI_LINKSET_USE_EXCLUSION_VOLUME)); - llassert(mEditLinksetUseExclusionVolume != NULL); - - mEditLinksetUseDynamicPhantom = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kDynamicPhantom), XUI_LINKSET_USE_DYNAMIC_PHANTOM)); - llassert(mEditLinksetUseDynamicPhantom != NULL); - - mEditLinksetUse->selectFirstItem(); - - mLabelWalkabilityCoefficients = findChild("walkability_coefficients_label"); - llassert(mLabelWalkabilityCoefficients != NULL); - - mLabelEditA = findChild("edit_a_label"); - llassert(mLabelEditA != NULL); - - mEditA = findChild("edit_a_value"); - llassert(mEditA != NULL); - mEditA->setPrevalidate(LLTextValidate::validateNonNegativeS32); - mEditA->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); - - mLabelEditB = findChild("edit_b_label"); - llassert(mLabelEditB != NULL); - - mEditB = findChild("edit_b_value"); - llassert(mEditB != NULL); - mEditB->setPrevalidate(LLTextValidate::validateNonNegativeS32); - mEditB->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); - - mLabelEditC = findChild("edit_c_label"); - llassert(mLabelEditC != NULL); - - mEditC = findChild("edit_c_value"); - llassert(mEditC != NULL); - mEditC->setPrevalidate(LLTextValidate::validateNonNegativeS32); - mEditC->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); - - mLabelEditD = findChild("edit_d_label"); - llassert(mLabelEditD != NULL); - - mEditD = findChild("edit_d_value"); - llassert(mEditD != NULL); - mEditD->setPrevalidate(LLTextValidate::validateNonNegativeS32); - mEditD->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); - - mApplyEditsButton = findChild("apply_edit_values"); - llassert(mApplyEditsButton != NULL); - mApplyEditsButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyChangesClicked, this)); - - return LLFloater::postBuild(); -} - -void LLFloaterPathfindingLinksets::onOpen(const LLSD& pKey) -{ - LLFloater::onOpen(pKey); - - requestGetLinksets(); - selectNoneLinksets(); - mLinksetsScrollList->setCommitOnSelectionChange(true); - - if (!mAgentStateSlot.connected()) - { - mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingLinksets::onAgentStateCB, this, _1)); - } - - if (!mSelectionUpdateSlot.connected()) - { - mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterPathfindingLinksets::updateControls, this)); - } - - if (!mRegionBoundarySlot.connected()) - { - mRegionBoundarySlot = LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterPathfindingLinksets::onRegionBoundaryCross, this)); - } -} - -void LLFloaterPathfindingLinksets::onClose(bool pAppQuitting) -{ - if (mRegionBoundarySlot.connected()) - { - mRegionBoundarySlot.disconnect(); - } - - if (mSelectionUpdateSlot.connected()) - { - mSelectionUpdateSlot.disconnect(); - } - - if (mAgentStateSlot.connected()) - { - mAgentStateSlot.disconnect(); - } - - mLinksetsScrollList->setCommitOnSelectionChange(false); - selectNoneLinksets(); - if (mLinksetsSelection.notNull()) - { - mLinksetsSelection.clear(); - } - - LLFloater::onClose(pAppQuitting); -} - -void LLFloaterPathfindingLinksets::draw() -{ - if (mShowBeaconCheckBox->get()) - { - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - int numSelectedItems = selectedItems.size(); - - std::vector viewerObjects; - viewerObjects.reserve(numSelectedItems); - - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - selectedItemIter != selectedItems.end(); ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - - LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); - if (viewerObject != NULL) - { - const std::string &objectName = selectedItem->getColumn(0)->getValue().asString(); - gObjectList.addDebugBeacon(viewerObject->getPositionAgent(), objectName, LLColor4(0.f, 0.f, 1.f, 0.8f), LLColor4(1.f, 1.f, 1.f, 1.f), 6); - } - } - } - } - - LLFloater::draw(); -} - -void LLFloaterPathfindingLinksets::openLinksetsEditor() -{ - LLFloaterReg::toggleInstanceOrBringToFront("pathfinding_linksets"); -} - -LLFloaterPathfindingLinksets::LLFloaterPathfindingLinksets(const LLSD& pSeed) - : LLFloater(pSeed), - mFilterByName(NULL), - mFilterByDescription(NULL), - mFilterByLinksetUse(NULL), - mLinksetsScrollList(NULL), - mLinksetsStatus(NULL), - mRefreshListButton(NULL), - mSelectAllButton(NULL), - mSelectNoneButton(NULL), - mShowBeaconCheckBox(NULL), - mTakeButton(NULL), - mTakeCopyButton(NULL), - mReturnButton(NULL), - mDeleteButton(NULL), - mTeleportButton(NULL), - mEditLinksetUse(NULL), - mLabelWalkabilityCoefficients(NULL), - mLabelEditA(NULL), - mEditA(NULL), - mLabelEditB(NULL), - mEditB(NULL), - mLabelEditC(NULL), - mEditC(NULL), - mLabelEditD(NULL), - mEditD(NULL), - mApplyEditsButton(NULL), - mMessagingState(kMessagingUnknown), - mMessagingRequestId(0U), - mLinksetsListPtr(), - mLinksetsSelection(), - mAgentStateSlot(), - mSelectionUpdateSlot() -{ -} - -LLFloaterPathfindingLinksets::~LLFloaterPathfindingLinksets() -{ -} - -LLFloaterPathfindingLinksets::EMessagingState LLFloaterPathfindingLinksets::getMessagingState() const -{ - return mMessagingState; -} - -void LLFloaterPathfindingLinksets::setMessagingState(EMessagingState pMessagingState) -{ - mMessagingState = pMessagingState; - updateControls(); -} - -void LLFloaterPathfindingLinksets::requestGetLinksets() -{ - switch (LLPathfindingManager::getInstance()->requestGetLinksets(++mMessagingRequestId, boost::bind(&LLFloaterPathfindingLinksets::handleNewLinksets, this, _1, _2, _3))) - { - case LLPathfindingManager::kRequestStarted : - setMessagingState(kMessagingGetRequestSent); - break; - case LLPathfindingManager::kRequestCompleted : - clearLinksets(); - setMessagingState(kMessagingComplete); - break; - case LLPathfindingManager::kRequestNotEnabled : - clearLinksets(); - setMessagingState(kMessagingNotEnabled); - break; - case LLPathfindingManager::kRequestError : - setMessagingState(kMessagingGetError); - break; - default : - setMessagingState(kMessagingGetError); - llassert(0); - break; - } -} - -void LLFloaterPathfindingLinksets::requestSetLinksets(LLPathfindingLinksetListPtr pLinksetList, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) -{ - switch (LLPathfindingManager::getInstance()->requestSetLinksets(++mMessagingRequestId, pLinksetList, pLinksetUse, pA, pB, pC, pD, boost::bind(&LLFloaterPathfindingLinksets::handleUpdateLinksets, this, _1, _2, _3))) - { - case LLPathfindingManager::kRequestStarted : - setMessagingState(kMessagingSetRequestSent); - break; - case LLPathfindingManager::kRequestCompleted : - setMessagingState(kMessagingComplete); - break; - case LLPathfindingManager::kRequestNotEnabled : - clearLinksets(); - setMessagingState(kMessagingNotEnabled); - break; - case LLPathfindingManager::kRequestError : - setMessagingState(kMessagingSetError); - break; - default : - setMessagingState(kMessagingSetError); - llassert(0); - break; - } -} - -void LLFloaterPathfindingLinksets::handleNewLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr) -{ - llassert(pRequestId <= mMessagingRequestId); - if (pRequestId == mMessagingRequestId) - { - mLinksetsListPtr = pLinksetsListPtr; - updateScrollList(); - - switch (pLinksetsRequestStatus) - { - case LLPathfindingManager::kRequestCompleted : - setMessagingState(kMessagingComplete); - break; - case LLPathfindingManager::kRequestError : - setMessagingState(kMessagingGetError); - break; - default : - setMessagingState(kMessagingGetError); - llassert(0); - break; - } - } -} - -void LLFloaterPathfindingLinksets::handleUpdateLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr) -{ - llassert(pRequestId <= mMessagingRequestId); - if (pRequestId == mMessagingRequestId) - { - if (mLinksetsListPtr == NULL) - { - mLinksetsListPtr = pLinksetsListPtr; - } - else - { - mLinksetsListPtr->update(*pLinksetsListPtr); - } - updateScrollList(); - - switch (pLinksetsRequestStatus) - { - case LLPathfindingManager::kRequestCompleted : - setMessagingState(kMessagingComplete); - break; - case LLPathfindingManager::kRequestError : - setMessagingState(kMessagingSetError); - break; - default : - setMessagingState(kMessagingSetError); - llassert(0); - break; - } - } -} - -void LLFloaterPathfindingLinksets::onApplyAllFilters() -{ - applyFilters(); -} - -void LLFloaterPathfindingLinksets::onClearFiltersClicked() -{ - clearFilters(); -} - -void LLFloaterPathfindingLinksets::onLinksetsSelectionChange() -{ - mLinksetsSelection.clear(); - LLSelectMgr::getInstance()->deselectAll(); - - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - int numSelectedItems = selectedItems.size(); - - std::vectorviewerObjects; - viewerObjects.reserve(numSelectedItems); - - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - selectedItemIter != selectedItems.end(); ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - - LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); - if (viewerObject != NULL) - { - viewerObjects.push_back(viewerObject); - } - } - - if (!viewerObjects.empty()) - { - mLinksetsSelection = LLSelectMgr::getInstance()->selectObjectAndFamily(viewerObjects); - } - } - - updateEditFieldValues(); - updateControls(); -} - -void LLFloaterPathfindingLinksets::onRefreshLinksetsClicked() -{ - requestGetLinksets(); -} - -void LLFloaterPathfindingLinksets::onSelectAllLinksetsClicked() -{ - selectAllLinksets(); -} - -void LLFloaterPathfindingLinksets::onSelectNoneLinksetsClicked() -{ - selectNoneLinksets(); -} - -void LLFloaterPathfindingLinksets::onTakeClicked() -{ - handle_take(); -} - -void LLFloaterPathfindingLinksets::onTakeCopyClicked() -{ - handle_take_copy(); -} - -void LLFloaterPathfindingLinksets::onReturnClicked() -{ - handle_object_return(); -} - -void LLFloaterPathfindingLinksets::onDeleteClicked() -{ - handle_object_delete(); -} - -void LLFloaterPathfindingLinksets::onTeleportClicked() -{ - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - llassert(selectedItems.size() == 1); - if (selectedItems.size() == 1) - { - std::vector::const_reference selectedItemRef = selectedItems.front(); - const LLScrollListItem *selectedItem = selectedItemRef; - llassert(mLinksetsListPtr != NULL); - LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); - const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - const LLVector3 &linksetLocation = linksetPtr->getLocation(); - - LLViewerRegion* region = gAgent.getRegion(); - if (region != NULL) - { - gAgent.teleportRequest(region->getHandle(), linksetLocation, true); - } - } -} - -void LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered(LLUICtrl *pUICtrl) -{ - LLLineEditor *pLineEditor = static_cast(pUICtrl); - llassert(pLineEditor != NULL); - - const std::string &valueString = pLineEditor->getText(); - S32 value = static_cast(atoi(valueString.c_str())); - - if ((value < LLPathfindingLinkset::MIN_WALKABILITY_VALUE) || (value > LLPathfindingLinkset::MAX_WALKABILITY_VALUE)) - { - value = llclamp(value, LLPathfindingLinkset::MIN_WALKABILITY_VALUE, LLPathfindingLinkset::MAX_WALKABILITY_VALUE); - pLineEditor->setValue(LLSD(value)); - } -} - -void LLFloaterPathfindingLinksets::onApplyChangesClicked() -{ - applyEdit(); -} - -void LLFloaterPathfindingLinksets::onAgentStateCB(LLPathfindingManager::EAgentState pAgentState) -{ - updateControls(); -} - -void LLFloaterPathfindingLinksets::onRegionBoundaryCross() -{ - requestGetLinksets(); -} - -void LLFloaterPathfindingLinksets::applyFilters() -{ - updateScrollList(); -} - -void LLFloaterPathfindingLinksets::clearFilters() -{ - mFilterByName->clear(); - mFilterByDescription->clear(); - setFilterLinksetUse(LLPathfindingLinkset::kUnknown); - updateScrollList(); -} - -void LLFloaterPathfindingLinksets::selectAllLinksets() -{ - mLinksetsScrollList->selectAll(); -} - -void LLFloaterPathfindingLinksets::selectNoneLinksets() -{ - mLinksetsScrollList->deselectAllItems(); -} - -void LLFloaterPathfindingLinksets::clearLinksets() -{ - if (mLinksetsListPtr != NULL) - { - mLinksetsListPtr->clear(); - } - updateScrollList(); -} - -void LLFloaterPathfindingLinksets::updateControls() -{ - updateStatusMessage(); - updateEnableStateOnListActions(); - updateEnableStateOnEditFields(); -} - -void LLFloaterPathfindingLinksets::updateEditFieldValues() -{ - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - int numSelectedItems = selectedItems.size(); - if (numSelectedItems <= 0) - { - mEditLinksetUse->selectFirstItem(); - mEditA->clear(); - mEditB->clear(); - mEditC->clear(); - mEditD->clear(); - } - else - { - LLScrollListItem *firstItem = selectedItems.front(); - - llassert(mLinksetsListPtr != NULL); - LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(firstItem->getUUID().asString()); - const LLPathfindingLinksetPtr linksetPtr(linksetIter->second); - - setEditLinksetUse(linksetPtr->getLinksetUse()); - mEditA->setValue(LLSD(linksetPtr->getWalkabilityCoefficientA())); - mEditB->setValue(LLSD(linksetPtr->getWalkabilityCoefficientB())); - mEditC->setValue(LLSD(linksetPtr->getWalkabilityCoefficientC())); - mEditD->setValue(LLSD(linksetPtr->getWalkabilityCoefficientD())); - updateEnableStateOnEditLinksetUse(); - } -} - -void LLFloaterPathfindingLinksets::updateScrollList() -{ - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - int numSelectedItems = selectedItems.size(); - uuid_vec_t selectedUUIDs; - if (numSelectedItems > 0) - { - selectedUUIDs.reserve(selectedItems.size()); - for (std::vector::const_iterator itemIter = selectedItems.begin(); - itemIter != selectedItems.end(); ++itemIter) - { - const LLScrollListItem *listItem = *itemIter; - selectedUUIDs.push_back(listItem->getUUID()); - } - } - - S32 origScrollPosition = mLinksetsScrollList->getScrollPos(); - mLinksetsScrollList->deleteAllItems(); - - if (mLinksetsListPtr != NULL) - { - std::string nameFilter = mFilterByName->getText(); - std::string descriptionFilter = mFilterByDescription->getText(); - LLPathfindingLinkset::ELinksetUse linksetUseFilter = getFilterLinksetUse(); - bool isFilteringName = !nameFilter.empty(); - bool isFilteringDescription = !descriptionFilter.empty(); - bool isFilteringLinksetUse = (linksetUseFilter != LLPathfindingLinkset::kUnknown); - - const LLVector3& avatarPosition = gAgent.getPositionAgent(); - - if (isFilteringName || isFilteringDescription || isFilteringLinksetUse) - { - LLStringUtil::toUpper(nameFilter); - LLStringUtil::toUpper(descriptionFilter); - for (LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->begin(); - linksetIter != mLinksetsListPtr->end(); ++linksetIter) - { - const LLPathfindingLinksetPtr linksetPtr(linksetIter->second); - std::string linksetName = (linksetPtr->isTerrain() ? getString("linkset_terrain_name") : linksetPtr->getName()); - std::string linksetDescription = linksetPtr->getDescription(); - LLStringUtil::toUpper(linksetName); - LLStringUtil::toUpper(linksetDescription); - if ((!isFilteringName || (linksetName.find(nameFilter) != std::string::npos)) && - (!isFilteringDescription || (linksetDescription.find(descriptionFilter) != std::string::npos)) && - (!isFilteringLinksetUse || (linksetPtr->getLinksetUse() == linksetUseFilter))) - { - LLSD element = buildLinksetScrollListElement(linksetPtr, avatarPosition); - mLinksetsScrollList->addElement(element); - } - } - } - else - { - for (LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->begin(); - linksetIter != mLinksetsListPtr->end(); ++linksetIter) - { - const LLPathfindingLinksetPtr linksetPtr(linksetIter->second); - LLSD element = buildLinksetScrollListElement(linksetPtr, avatarPosition); - mLinksetsScrollList->addElement(element); - } - } - } - - mLinksetsScrollList->selectMultiple(selectedUUIDs); - mLinksetsScrollList->setScrollPos(origScrollPosition); - updateEditFieldValues(); - updateControls(); -} - -LLSD LLFloaterPathfindingLinksets::buildLinksetScrollListElement(const LLPathfindingLinksetPtr pLinksetPtr, const LLVector3 &pAvatarPosition) const -{ - LLSD columns; - - if (pLinksetPtr->isTerrain()) - { - columns[0]["column"] = "name"; - columns[0]["value"] = getString("linkset_terrain_name"); - columns[0]["font"] = "SANSSERIF"; - - columns[1]["column"] = "description"; - columns[1]["value"] = getString("linkset_terrain_description"); - columns[1]["font"] = "SANSSERIF"; - - columns[2]["column"] = "land_impact"; - columns[2]["value"] = getString("linkset_terrain_land_impact"); - columns[2]["font"] = "SANSSERIF"; - - columns[3]["column"] = "dist_from_you"; - columns[3]["value"] = getString("linkset_terrain_dist_from_you"); - columns[3]["font"] = "SANSSERIF"; - } - else - { - columns[0]["column"] = "name"; - columns[0]["value"] = pLinksetPtr->getName(); - columns[0]["font"] = "SANSSERIF"; - - columns[1]["column"] = "description"; - columns[1]["value"] = pLinksetPtr->getDescription(); - columns[1]["font"] = "SANSSERIF"; - - columns[2]["column"] = "land_impact"; - columns[2]["value"] = llformat("%1d", pLinksetPtr->getLandImpact()); - columns[2]["font"] = "SANSSERIF"; - - columns[3]["column"] = "dist_from_you"; - columns[3]["value"] = llformat("%1.0f m", dist_vec(pAvatarPosition, pLinksetPtr->getLocation())); - columns[3]["font"] = "SANSSERIF"; - } - - columns[4]["column"] = "linkset_use"; - std::string linksetUse = getLinksetUseString(pLinksetPtr->getLinksetUse()); - if (pLinksetPtr->isTerrain()) - { - linksetUse += (" " + getString("linkset_is_terrain")); - } - else if (!pLinksetPtr->isModifiable() && pLinksetPtr->canBeVolume()) - { - linksetUse += (" " + getString("linkset_is_restricted_state")); - } - else if (pLinksetPtr->isModifiable() && !pLinksetPtr->canBeVolume()) - { - linksetUse += (" " + getString("linkset_is_non_volume_state")); - } - else if (!pLinksetPtr->isModifiable() && !pLinksetPtr->canBeVolume()) - { - linksetUse += (" " + getString("linkset_is_restricted_non_volume_state")); - } - columns[4]["value"] = linksetUse; - columns[4]["font"] = "SANSSERIF"; - - columns[5]["column"] = "a_percent"; - columns[5]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientA()); - columns[5]["font"] = "SANSSERIF"; - - columns[6]["column"] = "b_percent"; - columns[6]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientB()); - columns[6]["font"] = "SANSSERIF"; - - columns[7]["column"] = "c_percent"; - columns[7]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientC()); - columns[7]["font"] = "SANSSERIF"; - - columns[8]["column"] = "d_percent"; - columns[8]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientD()); - columns[8]["font"] = "SANSSERIF"; - - LLSD element; - element["id"] = pLinksetPtr->getUUID().asString(); - element["column"] = columns; - - return element; -} - -LLSD LLFloaterPathfindingLinksets::buildLinksetUseScrollListElement(const std::string &label, S32 value) const -{ - LLSD columns; - - columns[0]["column"] = "name"; - columns[0]["relwidth"] = static_cast(100.0f); - columns[0]["value"] = label; - columns[0]["font"] = "SANSSERIF"; - - LLSD element; - element["value"] = value; - element["column"] = columns; - - return element; -} - -bool LLFloaterPathfindingLinksets::isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const -{ - bool showWarning = false; - - if (linksetUse != LLPathfindingLinkset::kUnknown) - { - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - !showWarning && (selectedItemIter != selectedItems.end()); ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - llassert(mLinksetsListPtr != NULL); - LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); - llassert(linksetIter != mLinksetsListPtr->end()); - const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - showWarning = linksetPtr->isShowUnmodifiablePhantomWarning(linksetUse); - } - } - } - - return showWarning; -} - -bool LLFloaterPathfindingLinksets::isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const -{ - bool showWarning = false; - - if (linksetUse != LLPathfindingLinkset::kUnknown) - { - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - !showWarning && (selectedItemIter != selectedItems.end()); ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - llassert(mLinksetsListPtr != NULL); - LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); - llassert(linksetIter != mLinksetsListPtr->end()); - const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - showWarning = linksetPtr->isShowCannotBeVolumeWarning(linksetUse); - } - } - } - - return showWarning; -} - -void LLFloaterPathfindingLinksets::updateStatusMessage() -{ - static const LLColor4 errorColor = LLUIColorTable::instance().getColor("PathfindingErrorColor"); - static const LLColor4 warningColor = LLUIColorTable::instance().getColor("PathfindingWarningColor"); - - std::string statusText(""); - LLStyle::Params styleParams; - - switch (getMessagingState()) - { - case kMessagingUnknown: - statusText = getString("linksets_messaging_initial"); - styleParams.color = errorColor; - break; - case kMessagingGetRequestSent : - statusText = getString("linksets_messaging_get_inprogress"); - styleParams.color = warningColor; - break; - case kMessagingGetError : - statusText = getString("linksets_messaging_get_error"); - styleParams.color = errorColor; - break; - case kMessagingSetRequestSent : - statusText = getString("linksets_messaging_set_inprogress"); - styleParams.color = warningColor; - break; - case kMessagingSetError : - statusText = getString("linksets_messaging_set_error"); - styleParams.color = errorColor; - break; - case kMessagingComplete : - if (mLinksetsScrollList->isEmpty()) - { - statusText = getString("linksets_messaging_complete_none_found"); - } - else - { - S32 numItems = mLinksetsScrollList->getItemCount(); - S32 numSelectedItems = mLinksetsScrollList->getNumSelected(); - - LLLocale locale(LLStringUtil::getLocale()); - std::string numItemsString; - LLResMgr::getInstance()->getIntegerString(numItemsString, numItems); - - std::string numSelectedItemsString; - LLResMgr::getInstance()->getIntegerString(numSelectedItemsString, numSelectedItems); - - LLStringUtil::format_map_t string_args; - string_args["[NUM_SELECTED]"] = numSelectedItemsString; - string_args["[NUM_TOTAL]"] = numItemsString; - statusText = getString("linksets_messaging_complete_available", string_args); - } - break; - case kMessagingNotEnabled : - statusText = getString("linksets_messaging_not_enabled"); - styleParams.color = errorColor; - break; - default: - statusText = getString("linksets_messaging_initial"); - styleParams.color = errorColor; - llassert(0); - break; - } - - mLinksetsStatus->setText((LLStringExplicit)statusText, styleParams); -} - -void LLFloaterPathfindingLinksets::updateEnableStateOnListActions() -{ - switch (getMessagingState()) - { - case kMessagingUnknown: - case kMessagingGetRequestSent : - case kMessagingSetRequestSent : - mRefreshListButton->setEnabled(FALSE); - mSelectAllButton->setEnabled(FALSE); - mSelectNoneButton->setEnabled(FALSE); - break; - case kMessagingGetError : - case kMessagingSetError : - case kMessagingNotEnabled : - mRefreshListButton->setEnabled(TRUE); - mSelectAllButton->setEnabled(FALSE); - mSelectNoneButton->setEnabled(FALSE); - break; - case kMessagingComplete : - { - int numItems = mLinksetsScrollList->getItemCount(); - int numSelectedItems = mLinksetsScrollList->getNumSelected(); - mRefreshListButton->setEnabled(TRUE); - mSelectAllButton->setEnabled(numSelectedItems < numItems); - mSelectNoneButton->setEnabled(numSelectedItems > 0); - } - break; - default: - llassert(0); - break; - } -} - -void LLFloaterPathfindingLinksets::updateEnableStateOnEditFields() -{ - int numSelectedItems = mLinksetsScrollList->getNumSelected(); - bool isEditEnabled = ((numSelectedItems > 0) && LLPathfindingManager::getInstance()->isAllowAlterPermanent()); - - mShowBeaconCheckBox->setEnabled(numSelectedItems > 0); - mTakeButton->setEnabled(isEditEnabled && visible_take_object()); - mTakeCopyButton->setEnabled(isEditEnabled && enable_object_take_copy()); - mReturnButton->setEnabled(isEditEnabled && enable_object_return()); - mDeleteButton->setEnabled(isEditEnabled && enable_object_delete()); - mTeleportButton->setEnabled(numSelectedItems == 1); - - mEditLinksetUse->setEnabled(isEditEnabled); - - mLabelWalkabilityCoefficients->setEnabled(isEditEnabled); - mLabelEditA->setEnabled(isEditEnabled); - mLabelEditB->setEnabled(isEditEnabled); - mLabelEditC->setEnabled(isEditEnabled); - mLabelEditD->setEnabled(isEditEnabled); - mEditA->setEnabled(isEditEnabled); - mEditB->setEnabled(isEditEnabled); - mEditC->setEnabled(isEditEnabled); - mEditD->setEnabled(isEditEnabled); - - mApplyEditsButton->setEnabled(isEditEnabled && (getMessagingState() == kMessagingComplete)); -} - -void LLFloaterPathfindingLinksets::updateEnableStateOnEditLinksetUse() -{ - BOOL useWalkable = FALSE; - BOOL useStaticObstacle = FALSE; - BOOL useDynamicObstacle = FALSE; - BOOL useMaterialVolume = FALSE; - BOOL useExclusionVolume = FALSE; - BOOL useDynamicPhantom = FALSE; - - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); - !(useWalkable && useStaticObstacle && useDynamicObstacle && useMaterialVolume && useExclusionVolume && useDynamicPhantom) && (selectedItemIter != selectedItems.end()); - ++selectedItemIter) - { - const LLScrollListItem *selectedItem = *selectedItemIter; - llassert(mLinksetsListPtr != NULL); - LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); - llassert(linksetIter != mLinksetsListPtr->end()); - const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - - if (linksetPtr->isTerrain()) - { - useWalkable = TRUE; - } - else - { - if (linksetPtr->isModifiable()) - { - useWalkable = TRUE; - useStaticObstacle = TRUE; - useDynamicObstacle = TRUE; - useDynamicPhantom = TRUE; - if (linksetPtr->canBeVolume()) - { - useMaterialVolume = TRUE; - useExclusionVolume = TRUE; - } - } - else if (linksetPtr->isPhantom()) - { - useDynamicPhantom = TRUE; - if (linksetPtr->canBeVolume()) - { - useMaterialVolume = TRUE; - useExclusionVolume = TRUE; - } - } - else - { - useWalkable = TRUE; - useStaticObstacle = TRUE; - useDynamicObstacle = TRUE; - } - } - } - } - - mEditLinksetUseWalkable->setEnabled(useWalkable); - mEditLinksetUseStaticObstacle->setEnabled(useStaticObstacle); - mEditLinksetUseDynamicObstacle->setEnabled(useDynamicObstacle); - mEditLinksetUseMaterialVolume->setEnabled(useMaterialVolume); - mEditLinksetUseExclusionVolume->setEnabled(useExclusionVolume); - mEditLinksetUseDynamicPhantom->setEnabled(useDynamicPhantom); -} - -void LLFloaterPathfindingLinksets::applyEdit() -{ - LLPathfindingLinkset::ELinksetUse linksetUse = getEditLinksetUse(); - - bool showUnmodifiablePhantomWarning = isShowUnmodifiablePhantomWarning(linksetUse); - bool showCannotBeVolumeWarning = isShowCannotBeVolumeWarning(linksetUse); - - if (showUnmodifiablePhantomWarning || showCannotBeVolumeWarning) - { - LLPathfindingLinkset::ELinksetUse restrictedLinksetUse = LLPathfindingLinkset::getLinksetUseWithToggledPhantom(linksetUse); - LLSD substitutions; - substitutions["REQUESTED_TYPE"] = getLinksetUseString(linksetUse); - substitutions["RESTRICTED_TYPE"] = getLinksetUseString(restrictedLinksetUse); - - std::string notificationName; - if (showUnmodifiablePhantomWarning && showCannotBeVolumeWarning) - { - notificationName = "PathfindingLinksets_SetLinksetUseMismatchOnRestrictedAndVolume"; - } - else if (showUnmodifiablePhantomWarning) - { - notificationName = "PathfindingLinksets_SetLinksetUseMismatchOnRestricted"; - } - else - { - notificationName = "PathfindingLinksets_SetLinksetUseMismatchOnVolume"; - } - LLNotificationsUtil::add(notificationName, substitutions, LLSD(), boost::bind(&LLFloaterPathfindingLinksets::handleApplyEdit, this, _1, _2)); - } - else - { - doApplyEdit(); - } -} - -void LLFloaterPathfindingLinksets::handleApplyEdit(const LLSD &pNotification, const LLSD &pResponse) -{ - if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) - { - doApplyEdit(); - } -} - -void LLFloaterPathfindingLinksets::doApplyEdit() -{ - std::vector selectedItems = mLinksetsScrollList->getAllSelected(); - if (!selectedItems.empty()) - { - LLPathfindingLinkset::ELinksetUse linksetUse = getEditLinksetUse(); - const std::string &aString = mEditA->getText(); - const std::string &bString = mEditB->getText(); - const std::string &cString = mEditC->getText(); - const std::string &dString = mEditD->getText(); - S32 aValue = static_cast(atoi(aString.c_str())); - S32 bValue = static_cast(atoi(bString.c_str())); - S32 cValue = static_cast(atoi(cString.c_str())); - S32 dValue = static_cast(atoi(dString.c_str())); - - LLPathfindingLinksetListPtr editListPtr(new LLPathfindingLinksetList()); - for (std::vector::const_iterator itemIter = selectedItems.begin(); - itemIter != selectedItems.end(); ++itemIter) - { - const LLScrollListItem *listItem = *itemIter; - LLUUID uuid = listItem->getUUID(); - const std::string &uuidString = uuid.asString(); - llassert(mLinksetsListPtr != NULL); - LLPathfindingLinksetList::iterator linksetIter = mLinksetsListPtr->find(uuidString); - llassert(linksetIter != mLinksetsListPtr->end()); - LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - editListPtr->insert(std::pair(uuidString, linksetPtr)); - } - - requestSetLinksets(editListPtr, linksetUse, aValue, bValue, cValue, dValue); - } -} - -std::string LLFloaterPathfindingLinksets::getLinksetUseString(LLPathfindingLinkset::ELinksetUse pLinksetUse) const -{ - std::string linksetUse; - - switch (pLinksetUse) - { - case LLPathfindingLinkset::kWalkable : - linksetUse = getString("linkset_use_walkable"); - break; - case LLPathfindingLinkset::kStaticObstacle : - linksetUse = getString("linkset_use_static_obstacle"); - break; - case LLPathfindingLinkset::kDynamicObstacle : - linksetUse = getString("linkset_use_dynamic_obstacle"); - break; - case LLPathfindingLinkset::kMaterialVolume : - linksetUse = getString("linkset_use_material_volume"); - break; - case LLPathfindingLinkset::kExclusionVolume : - linksetUse = getString("linkset_use_exclusion_volume"); - break; - case LLPathfindingLinkset::kDynamicPhantom : - linksetUse = getString("linkset_use_dynamic_phantom"); - break; - case LLPathfindingLinkset::kUnknown : - default : - linksetUse = getString("linkset_use_dynamic_obstacle"); - llassert(0); - break; - } - - return linksetUse; -} - -LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::getFilterLinksetUse() const -{ - return convertToLinksetUse(mFilterByLinksetUse->getValue()); -} - -void LLFloaterPathfindingLinksets::setFilterLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse) -{ - mFilterByLinksetUse->setValue(convertToXuiValue(pLinksetUse)); -} - -LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::getEditLinksetUse() const -{ - return convertToLinksetUse(mEditLinksetUse->getValue()); -} - -void LLFloaterPathfindingLinksets::setEditLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse) -{ - mEditLinksetUse->setValue(convertToXuiValue(pLinksetUse)); -} - -LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::convertToLinksetUse(LLSD pXuiValue) const -{ - LLPathfindingLinkset::ELinksetUse linkUse; - - switch (pXuiValue.asInteger()) - { - case XUI_LINKSET_USE_NONE : - linkUse = LLPathfindingLinkset::kUnknown; - break; - case XUI_LINKSET_USE_WALKABLE : - linkUse = LLPathfindingLinkset::kWalkable; - break; - case XUI_LINKSET_USE_STATIC_OBSTACLE : - linkUse = LLPathfindingLinkset::kStaticObstacle; - break; - case XUI_LINKSET_USE_DYNAMIC_OBSTACLE : - linkUse = LLPathfindingLinkset::kDynamicObstacle; - break; - case XUI_LINKSET_USE_MATERIAL_VOLUME : - linkUse = LLPathfindingLinkset::kMaterialVolume; - break; - case XUI_LINKSET_USE_EXCLUSION_VOLUME : - linkUse = LLPathfindingLinkset::kExclusionVolume; - break; - case XUI_LINKSET_USE_DYNAMIC_PHANTOM : - linkUse = LLPathfindingLinkset::kDynamicPhantom; - break; - default : - linkUse = LLPathfindingLinkset::kUnknown; - llassert(0); - break; - } - - return linkUse; -} - -LLSD LLFloaterPathfindingLinksets::convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const -{ - LLSD xuiValue; - - switch (pLinksetUse) - { - case LLPathfindingLinkset::kUnknown : - xuiValue = XUI_LINKSET_USE_NONE; - break; - case LLPathfindingLinkset::kWalkable : - xuiValue = XUI_LINKSET_USE_WALKABLE; - break; - case LLPathfindingLinkset::kStaticObstacle : - xuiValue = XUI_LINKSET_USE_STATIC_OBSTACLE; - break; - case LLPathfindingLinkset::kDynamicObstacle : - xuiValue = XUI_LINKSET_USE_DYNAMIC_OBSTACLE; - break; - case LLPathfindingLinkset::kMaterialVolume : - xuiValue = XUI_LINKSET_USE_MATERIAL_VOLUME; - break; - case LLPathfindingLinkset::kExclusionVolume : - xuiValue = XUI_LINKSET_USE_EXCLUSION_VOLUME; - break; - case LLPathfindingLinkset::kDynamicPhantom : - xuiValue = XUI_LINKSET_USE_DYNAMIC_PHANTOM; - break; - default : - xuiValue = XUI_LINKSET_USE_NONE; - llassert(0); - break; - } - - return xuiValue; -} +/** +* @file llfloaterpathfindinglinksets.cpp +* @author William Todd Stinson +* @brief "Pathfinding linksets" floater, allowing manipulation of the Havok AI pathfinding settings. +* +* $LicenseInfo:firstyear=2002&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llfloaterpathfindinglinksets.h" +#include "llsd.h" +#include "lluuid.h" +#include "v3math.h" +#include "lltextvalidate.h" +#include "llagent.h" +#include "lltextbase.h" +#include "lllineeditor.h" +#include "llscrolllistitem.h" +#include "llscrolllistctrl.h" +#include "llcombobox.h" +#include "llcheckboxctrl.h" +#include "llbutton.h" +#include "llresmgr.h" +#include "llviewerregion.h" +#include "llselectmgr.h" +#include "llviewermenu.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llpathfindinglinkset.h" +#include "llpathfindinglinksetlist.h" +#include "llpathfindingmanager.h" +#include "llnotificationsutil.h" +#include "llenvmanager.h" + +#include +#include + +#define XUI_LINKSET_USE_NONE 0 +#define XUI_LINKSET_USE_WALKABLE 1 +#define XUI_LINKSET_USE_STATIC_OBSTACLE 2 +#define XUI_LINKSET_USE_DYNAMIC_OBSTACLE 3 +#define XUI_LINKSET_USE_MATERIAL_VOLUME 4 +#define XUI_LINKSET_USE_EXCLUSION_VOLUME 5 +#define XUI_LINKSET_USE_DYNAMIC_PHANTOM 6 + +//--------------------------------------------------------------------------- +// LLFloaterPathfindingLinksets +//--------------------------------------------------------------------------- + +BOOL LLFloaterPathfindingLinksets::postBuild() +{ + childSetAction("apply_filters", boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + childSetAction("clear_filters", boost::bind(&LLFloaterPathfindingLinksets::onClearFiltersClicked, this)); + + mFilterByName = findChild("filter_by_name"); + llassert(mFilterByName != NULL); + mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByName->setSelectAllonFocusReceived(true); + mFilterByName->setCommitOnFocusLost(true); + + mFilterByDescription = findChild("filter_by_description"); + llassert(mFilterByDescription != NULL); + mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByDescription->setSelectAllonFocusReceived(true); + mFilterByDescription->setCommitOnFocusLost(true); + + mFilterByLinksetUse = findChild("filter_by_linkset_use"); + llassert(mFilterByLinksetUse != NULL); + mFilterByLinksetUse->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + + mLinksetsScrollList = findChild("pathfinding_linksets"); + llassert(mLinksetsScrollList != NULL); + mLinksetsScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onLinksetsSelectionChange, this)); + mLinksetsScrollList->sortByColumnIndex(0, true); + + mLinksetsStatus = findChild("linksets_status"); + llassert(mLinksetsStatus != NULL); + + mRefreshListButton = findChild("refresh_linksets_list"); + llassert(mRefreshListButton != NULL); + mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onRefreshLinksetsClicked, this)); + + mSelectAllButton = findChild("select_all_linksets"); + llassert(mSelectAllButton != NULL); + mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectAllLinksetsClicked, this)); + + mSelectNoneButton = findChild("select_none_linksets"); + llassert(mSelectNoneButton != NULL); + mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectNoneLinksetsClicked, this)); + + mShowBeaconCheckBox = findChild("show_beacon"); + llassert(mShowBeaconCheckBox != NULL); + + mTakeButton = findChild("take_linksets"); + llassert(mTakeButton != NULL); + mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeClicked, this)); + + mTakeCopyButton = findChild("take_copy_linksets"); + llassert(mTakeCopyButton != NULL); + mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeCopyClicked, this)); + + mReturnButton = findChild("return_linksets"); + llassert(mReturnButton != NULL); + mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onReturnClicked, this)); + + mDeleteButton = findChild("delete_linksets"); + llassert(mDeleteButton != NULL); + mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onDeleteClicked, this)); + + mTeleportButton = findChild("teleport_me_to_linkset"); + llassert(mTeleportButton != NULL); + mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTeleportClicked, this)); + + mEditLinksetUse = findChild("edit_linkset_use"); + llassert(mEditLinksetUse != NULL); + + mEditLinksetUse->clearRows(); + + mEditLinksetUseUnset = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getString("linkset_choose_use"), XUI_LINKSET_USE_NONE)); + llassert(mEditLinksetUseUnset != NULL); + + mEditLinksetUseWalkable = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kWalkable), XUI_LINKSET_USE_WALKABLE)); + llassert(mEditLinksetUseWalkable != NULL); + + mEditLinksetUseStaticObstacle = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kStaticObstacle), XUI_LINKSET_USE_STATIC_OBSTACLE)); + llassert(mEditLinksetUseStaticObstacle != NULL); + + mEditLinksetUseDynamicObstacle = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kDynamicObstacle), XUI_LINKSET_USE_DYNAMIC_OBSTACLE)); + llassert(mEditLinksetUseDynamicObstacle != NULL); + + mEditLinksetUseMaterialVolume = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kMaterialVolume), XUI_LINKSET_USE_MATERIAL_VOLUME)); + llassert(mEditLinksetUseMaterialVolume != NULL); + + mEditLinksetUseExclusionVolume = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kExclusionVolume), XUI_LINKSET_USE_EXCLUSION_VOLUME)); + llassert(mEditLinksetUseExclusionVolume != NULL); + + mEditLinksetUseDynamicPhantom = mEditLinksetUse->addElement(buildLinksetUseScrollListElement(getLinksetUseString(LLPathfindingLinkset::kDynamicPhantom), XUI_LINKSET_USE_DYNAMIC_PHANTOM)); + llassert(mEditLinksetUseDynamicPhantom != NULL); + + mEditLinksetUse->selectFirstItem(); + + mLabelWalkabilityCoefficients = findChild("walkability_coefficients_label"); + llassert(mLabelWalkabilityCoefficients != NULL); + + mLabelEditA = findChild("edit_a_label"); + llassert(mLabelEditA != NULL); + + mEditA = findChild("edit_a_value"); + llassert(mEditA != NULL); + mEditA->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditA->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mLabelEditB = findChild("edit_b_label"); + llassert(mLabelEditB != NULL); + + mEditB = findChild("edit_b_value"); + llassert(mEditB != NULL); + mEditB->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditB->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mLabelEditC = findChild("edit_c_label"); + llassert(mLabelEditC != NULL); + + mEditC = findChild("edit_c_value"); + llassert(mEditC != NULL); + mEditC->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditC->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mLabelEditD = findChild("edit_d_label"); + llassert(mLabelEditD != NULL); + + mEditD = findChild("edit_d_value"); + llassert(mEditD != NULL); + mEditD->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditD->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mApplyEditsButton = findChild("apply_edit_values"); + llassert(mApplyEditsButton != NULL); + mApplyEditsButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyChangesClicked, this)); + + return LLFloater::postBuild(); +} + +void LLFloaterPathfindingLinksets::onOpen(const LLSD& pKey) +{ + LLFloater::onOpen(pKey); + + requestGetLinksets(); + selectNoneLinksets(); + mLinksetsScrollList->setCommitOnSelectionChange(true); + + if (!mAgentStateSlot.connected()) + { + mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingLinksets::onAgentStateCB, this, _1)); + } + + if (!mSelectionUpdateSlot.connected()) + { + mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterPathfindingLinksets::updateControls, this)); + } + + if (!mRegionBoundarySlot.connected()) + { + mRegionBoundarySlot = LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterPathfindingLinksets::onRegionBoundaryCross, this)); + } +} + +void LLFloaterPathfindingLinksets::onClose(bool pAppQuitting) +{ + if (mRegionBoundarySlot.connected()) + { + mRegionBoundarySlot.disconnect(); + } + + if (mSelectionUpdateSlot.connected()) + { + mSelectionUpdateSlot.disconnect(); + } + + if (mAgentStateSlot.connected()) + { + mAgentStateSlot.disconnect(); + } + + mLinksetsScrollList->setCommitOnSelectionChange(false); + selectNoneLinksets(); + if (mLinksetsSelection.notNull()) + { + mLinksetsSelection.clear(); + } + + LLFloater::onClose(pAppQuitting); +} + +void LLFloaterPathfindingLinksets::draw() +{ + if (mShowBeaconCheckBox->get()) + { + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + selectedItemIter != selectedItems.end(); ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + + LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); + if (viewerObject != NULL) + { + const std::string &objectName = selectedItem->getColumn(0)->getValue().asString(); + gObjectList.addDebugBeacon(viewerObject->getPositionAgent(), objectName, LLColor4(0.f, 0.f, 1.f, 0.8f), LLColor4(1.f, 1.f, 1.f, 1.f), 6); + } + } + } + } + + LLFloater::draw(); +} + +void LLFloaterPathfindingLinksets::openLinksetsEditor() +{ + LLFloaterReg::toggleInstanceOrBringToFront("pathfinding_linksets"); +} + +LLFloaterPathfindingLinksets::LLFloaterPathfindingLinksets(const LLSD& pSeed) + : LLFloater(pSeed), + mFilterByName(NULL), + mFilterByDescription(NULL), + mFilterByLinksetUse(NULL), + mLinksetsScrollList(NULL), + mLinksetsStatus(NULL), + mRefreshListButton(NULL), + mSelectAllButton(NULL), + mSelectNoneButton(NULL), + mShowBeaconCheckBox(NULL), + mTakeButton(NULL), + mTakeCopyButton(NULL), + mReturnButton(NULL), + mDeleteButton(NULL), + mTeleportButton(NULL), + mEditLinksetUse(NULL), + mLabelWalkabilityCoefficients(NULL), + mLabelEditA(NULL), + mEditA(NULL), + mLabelEditB(NULL), + mEditB(NULL), + mLabelEditC(NULL), + mEditC(NULL), + mLabelEditD(NULL), + mEditD(NULL), + mApplyEditsButton(NULL), + mMessagingState(kMessagingUnknown), + mMessagingRequestId(0U), + mLinksetsListPtr(), + mLinksetsSelection(), + mAgentStateSlot(), + mSelectionUpdateSlot() +{ +} + +LLFloaterPathfindingLinksets::~LLFloaterPathfindingLinksets() +{ +} + +LLFloaterPathfindingLinksets::EMessagingState LLFloaterPathfindingLinksets::getMessagingState() const +{ + return mMessagingState; +} + +void LLFloaterPathfindingLinksets::setMessagingState(EMessagingState pMessagingState) +{ + mMessagingState = pMessagingState; + updateControls(); +} + +void LLFloaterPathfindingLinksets::requestGetLinksets() +{ + switch (LLPathfindingManager::getInstance()->requestGetLinksets(++mMessagingRequestId, boost::bind(&LLFloaterPathfindingLinksets::handleNewLinksets, this, _1, _2, _3))) + { + case LLPathfindingManager::kRequestStarted : + setMessagingState(kMessagingGetRequestSent); + break; + case LLPathfindingManager::kRequestCompleted : + clearLinksets(); + setMessagingState(kMessagingComplete); + break; + case LLPathfindingManager::kRequestNotEnabled : + clearLinksets(); + setMessagingState(kMessagingNotEnabled); + break; + case LLPathfindingManager::kRequestError : + setMessagingState(kMessagingGetError); + break; + default : + setMessagingState(kMessagingGetError); + llassert(0); + break; + } +} + +void LLFloaterPathfindingLinksets::requestSetLinksets(LLPathfindingLinksetListPtr pLinksetList, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) +{ + switch (LLPathfindingManager::getInstance()->requestSetLinksets(++mMessagingRequestId, pLinksetList, pLinksetUse, pA, pB, pC, pD, boost::bind(&LLFloaterPathfindingLinksets::handleUpdateLinksets, this, _1, _2, _3))) + { + case LLPathfindingManager::kRequestStarted : + setMessagingState(kMessagingSetRequestSent); + break; + case LLPathfindingManager::kRequestCompleted : + setMessagingState(kMessagingComplete); + break; + case LLPathfindingManager::kRequestNotEnabled : + clearLinksets(); + setMessagingState(kMessagingNotEnabled); + break; + case LLPathfindingManager::kRequestError : + setMessagingState(kMessagingSetError); + break; + default : + setMessagingState(kMessagingSetError); + llassert(0); + break; + } +} + +void LLFloaterPathfindingLinksets::handleNewLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr) +{ + llassert(pRequestId <= mMessagingRequestId); + if (pRequestId == mMessagingRequestId) + { + mLinksetsListPtr = pLinksetsListPtr; + updateScrollList(); + + switch (pLinksetsRequestStatus) + { + case LLPathfindingManager::kRequestCompleted : + setMessagingState(kMessagingComplete); + break; + case LLPathfindingManager::kRequestError : + setMessagingState(kMessagingGetError); + break; + default : + setMessagingState(kMessagingGetError); + llassert(0); + break; + } + } +} + +void LLFloaterPathfindingLinksets::handleUpdateLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr) +{ + llassert(pRequestId <= mMessagingRequestId); + if (pRequestId == mMessagingRequestId) + { + if (mLinksetsListPtr == NULL) + { + mLinksetsListPtr = pLinksetsListPtr; + } + else + { + mLinksetsListPtr->update(*pLinksetsListPtr); + } + updateScrollList(); + + switch (pLinksetsRequestStatus) + { + case LLPathfindingManager::kRequestCompleted : + setMessagingState(kMessagingComplete); + break; + case LLPathfindingManager::kRequestError : + setMessagingState(kMessagingSetError); + break; + default : + setMessagingState(kMessagingSetError); + llassert(0); + break; + } + } +} + +void LLFloaterPathfindingLinksets::onApplyAllFilters() +{ + applyFilters(); +} + +void LLFloaterPathfindingLinksets::onClearFiltersClicked() +{ + clearFilters(); +} + +void LLFloaterPathfindingLinksets::onLinksetsSelectionChange() +{ + mLinksetsSelection.clear(); + LLSelectMgr::getInstance()->deselectAll(); + + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vectorviewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + selectedItemIter != selectedItems.end(); ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + + LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); + if (viewerObject != NULL) + { + viewerObjects.push_back(viewerObject); + } + } + + if (!viewerObjects.empty()) + { + mLinksetsSelection = LLSelectMgr::getInstance()->selectObjectAndFamily(viewerObjects); + } + } + + updateEditFieldValues(); + updateControls(); +} + +void LLFloaterPathfindingLinksets::onRefreshLinksetsClicked() +{ + requestGetLinksets(); +} + +void LLFloaterPathfindingLinksets::onSelectAllLinksetsClicked() +{ + selectAllLinksets(); +} + +void LLFloaterPathfindingLinksets::onSelectNoneLinksetsClicked() +{ + selectNoneLinksets(); +} + +void LLFloaterPathfindingLinksets::onTakeClicked() +{ + handle_take(); +} + +void LLFloaterPathfindingLinksets::onTakeCopyClicked() +{ + handle_take_copy(); +} + +void LLFloaterPathfindingLinksets::onReturnClicked() +{ + handle_object_return(); +} + +void LLFloaterPathfindingLinksets::onDeleteClicked() +{ + handle_object_delete(); +} + +void LLFloaterPathfindingLinksets::onTeleportClicked() +{ + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + llassert(selectedItems.size() == 1); + if (selectedItems.size() == 1) + { + std::vector::const_reference selectedItemRef = selectedItems.front(); + const LLScrollListItem *selectedItem = selectedItemRef; + llassert(mLinksetsListPtr != NULL); + LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); + const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + const LLVector3 &linksetLocation = linksetPtr->getLocation(); + + LLViewerRegion* region = gAgent.getRegion(); + if (region != NULL) + { + gAgent.teleportRequest(region->getHandle(), linksetLocation, true); + } + } +} + +void LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered(LLUICtrl *pUICtrl) +{ + LLLineEditor *pLineEditor = static_cast(pUICtrl); + llassert(pLineEditor != NULL); + + const std::string &valueString = pLineEditor->getText(); + S32 value = static_cast(atoi(valueString.c_str())); + + if ((value < LLPathfindingLinkset::MIN_WALKABILITY_VALUE) || (value > LLPathfindingLinkset::MAX_WALKABILITY_VALUE)) + { + value = llclamp(value, LLPathfindingLinkset::MIN_WALKABILITY_VALUE, LLPathfindingLinkset::MAX_WALKABILITY_VALUE); + pLineEditor->setValue(LLSD(value)); + } +} + +void LLFloaterPathfindingLinksets::onApplyChangesClicked() +{ + applyEdit(); +} + +void LLFloaterPathfindingLinksets::onAgentStateCB(LLPathfindingManager::EAgentState pAgentState) +{ + updateControls(); +} + +void LLFloaterPathfindingLinksets::onRegionBoundaryCross() +{ + requestGetLinksets(); +} + +void LLFloaterPathfindingLinksets::applyFilters() +{ + updateScrollList(); +} + +void LLFloaterPathfindingLinksets::clearFilters() +{ + mFilterByName->clear(); + mFilterByDescription->clear(); + setFilterLinksetUse(LLPathfindingLinkset::kUnknown); + updateScrollList(); +} + +void LLFloaterPathfindingLinksets::selectAllLinksets() +{ + mLinksetsScrollList->selectAll(); +} + +void LLFloaterPathfindingLinksets::selectNoneLinksets() +{ + mLinksetsScrollList->deselectAllItems(); +} + +void LLFloaterPathfindingLinksets::clearLinksets() +{ + if (mLinksetsListPtr != NULL) + { + mLinksetsListPtr->clear(); + } + updateScrollList(); +} + +void LLFloaterPathfindingLinksets::updateControls() +{ + updateStatusMessage(); + updateEnableStateOnListActions(); + updateEnableStateOnEditFields(); +} + +void LLFloaterPathfindingLinksets::updateEditFieldValues() +{ + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + int numSelectedItems = selectedItems.size(); + if (numSelectedItems <= 0) + { + mEditLinksetUse->selectFirstItem(); + mEditA->clear(); + mEditB->clear(); + mEditC->clear(); + mEditD->clear(); + } + else + { + LLScrollListItem *firstItem = selectedItems.front(); + + llassert(mLinksetsListPtr != NULL); + LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(firstItem->getUUID().asString()); + const LLPathfindingLinksetPtr linksetPtr(linksetIter->second); + + setEditLinksetUse(linksetPtr->getLinksetUse()); + mEditA->setValue(LLSD(linksetPtr->getWalkabilityCoefficientA())); + mEditB->setValue(LLSD(linksetPtr->getWalkabilityCoefficientB())); + mEditC->setValue(LLSD(linksetPtr->getWalkabilityCoefficientC())); + mEditD->setValue(LLSD(linksetPtr->getWalkabilityCoefficientD())); + updateEnableStateOnEditLinksetUse(); + } +} + +void LLFloaterPathfindingLinksets::updateScrollList() +{ + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + int numSelectedItems = selectedItems.size(); + uuid_vec_t selectedUUIDs; + if (numSelectedItems > 0) + { + selectedUUIDs.reserve(selectedItems.size()); + for (std::vector::const_iterator itemIter = selectedItems.begin(); + itemIter != selectedItems.end(); ++itemIter) + { + const LLScrollListItem *listItem = *itemIter; + selectedUUIDs.push_back(listItem->getUUID()); + } + } + + S32 origScrollPosition = mLinksetsScrollList->getScrollPos(); + mLinksetsScrollList->deleteAllItems(); + + if (mLinksetsListPtr != NULL) + { + std::string nameFilter = mFilterByName->getText(); + std::string descriptionFilter = mFilterByDescription->getText(); + LLPathfindingLinkset::ELinksetUse linksetUseFilter = getFilterLinksetUse(); + bool isFilteringName = !nameFilter.empty(); + bool isFilteringDescription = !descriptionFilter.empty(); + bool isFilteringLinksetUse = (linksetUseFilter != LLPathfindingLinkset::kUnknown); + + const LLVector3& avatarPosition = gAgent.getPositionAgent(); + + if (isFilteringName || isFilteringDescription || isFilteringLinksetUse) + { + LLStringUtil::toUpper(nameFilter); + LLStringUtil::toUpper(descriptionFilter); + for (LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->begin(); + linksetIter != mLinksetsListPtr->end(); ++linksetIter) + { + const LLPathfindingLinksetPtr linksetPtr(linksetIter->second); + std::string linksetName = (linksetPtr->isTerrain() ? getString("linkset_terrain_name") : linksetPtr->getName()); + std::string linksetDescription = linksetPtr->getDescription(); + LLStringUtil::toUpper(linksetName); + LLStringUtil::toUpper(linksetDescription); + if ((!isFilteringName || (linksetName.find(nameFilter) != std::string::npos)) && + (!isFilteringDescription || (linksetDescription.find(descriptionFilter) != std::string::npos)) && + (!isFilteringLinksetUse || (linksetPtr->getLinksetUse() == linksetUseFilter))) + { + LLSD element = buildLinksetScrollListElement(linksetPtr, avatarPosition); + mLinksetsScrollList->addElement(element); + } + } + } + else + { + for (LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->begin(); + linksetIter != mLinksetsListPtr->end(); ++linksetIter) + { + const LLPathfindingLinksetPtr linksetPtr(linksetIter->second); + LLSD element = buildLinksetScrollListElement(linksetPtr, avatarPosition); + mLinksetsScrollList->addElement(element); + } + } + } + + mLinksetsScrollList->selectMultiple(selectedUUIDs); + mLinksetsScrollList->setScrollPos(origScrollPosition); + updateEditFieldValues(); + updateControls(); +} + +LLSD LLFloaterPathfindingLinksets::buildLinksetScrollListElement(const LLPathfindingLinksetPtr pLinksetPtr, const LLVector3 &pAvatarPosition) const +{ + LLSD columns; + + if (pLinksetPtr->isTerrain()) + { + columns[0]["column"] = "name"; + columns[0]["value"] = getString("linkset_terrain_name"); + columns[0]["font"] = "SANSSERIF"; + + columns[1]["column"] = "description"; + columns[1]["value"] = getString("linkset_terrain_description"); + columns[1]["font"] = "SANSSERIF"; + + columns[2]["column"] = "land_impact"; + columns[2]["value"] = getString("linkset_terrain_land_impact"); + columns[2]["font"] = "SANSSERIF"; + + columns[3]["column"] = "dist_from_you"; + columns[3]["value"] = getString("linkset_terrain_dist_from_you"); + columns[3]["font"] = "SANSSERIF"; + } + else + { + columns[0]["column"] = "name"; + columns[0]["value"] = pLinksetPtr->getName(); + columns[0]["font"] = "SANSSERIF"; + + columns[1]["column"] = "description"; + columns[1]["value"] = pLinksetPtr->getDescription(); + columns[1]["font"] = "SANSSERIF"; + + columns[2]["column"] = "land_impact"; + columns[2]["value"] = llformat("%1d", pLinksetPtr->getLandImpact()); + columns[2]["font"] = "SANSSERIF"; + + columns[3]["column"] = "dist_from_you"; + columns[3]["value"] = llformat("%1.0f m", dist_vec(pAvatarPosition, pLinksetPtr->getLocation())); + columns[3]["font"] = "SANSSERIF"; + } + + columns[4]["column"] = "linkset_use"; + std::string linksetUse = getLinksetUseString(pLinksetPtr->getLinksetUse()); + if (pLinksetPtr->isTerrain()) + { + linksetUse += (" " + getString("linkset_is_terrain")); + } + else if (!pLinksetPtr->isModifiable() && pLinksetPtr->canBeVolume()) + { + linksetUse += (" " + getString("linkset_is_restricted_state")); + } + else if (pLinksetPtr->isModifiable() && !pLinksetPtr->canBeVolume()) + { + linksetUse += (" " + getString("linkset_is_non_volume_state")); + } + else if (!pLinksetPtr->isModifiable() && !pLinksetPtr->canBeVolume()) + { + linksetUse += (" " + getString("linkset_is_restricted_non_volume_state")); + } + columns[4]["value"] = linksetUse; + columns[4]["font"] = "SANSSERIF"; + + columns[5]["column"] = "a_percent"; + columns[5]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientA()); + columns[5]["font"] = "SANSSERIF"; + + columns[6]["column"] = "b_percent"; + columns[6]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientB()); + columns[6]["font"] = "SANSSERIF"; + + columns[7]["column"] = "c_percent"; + columns[7]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientC()); + columns[7]["font"] = "SANSSERIF"; + + columns[8]["column"] = "d_percent"; + columns[8]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientD()); + columns[8]["font"] = "SANSSERIF"; + + LLSD element; + element["id"] = pLinksetPtr->getUUID().asString(); + element["column"] = columns; + + return element; +} + +LLSD LLFloaterPathfindingLinksets::buildLinksetUseScrollListElement(const std::string &label, S32 value) const +{ + LLSD columns; + + columns[0]["column"] = "name"; + columns[0]["relwidth"] = static_cast(100.0f); + columns[0]["value"] = label; + columns[0]["font"] = "SANSSERIF"; + + LLSD element; + element["value"] = value; + element["column"] = columns; + + return element; +} + +bool LLFloaterPathfindingLinksets::isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const +{ + bool showWarning = false; + + if (linksetUse != LLPathfindingLinkset::kUnknown) + { + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + !showWarning && (selectedItemIter != selectedItems.end()); ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + llassert(mLinksetsListPtr != NULL); + LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); + llassert(linksetIter != mLinksetsListPtr->end()); + const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + showWarning = linksetPtr->isShowUnmodifiablePhantomWarning(linksetUse); + } + } + } + + return showWarning; +} + +bool LLFloaterPathfindingLinksets::isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const +{ + bool showWarning = false; + + if (linksetUse != LLPathfindingLinkset::kUnknown) + { + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + !showWarning && (selectedItemIter != selectedItems.end()); ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + llassert(mLinksetsListPtr != NULL); + LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); + llassert(linksetIter != mLinksetsListPtr->end()); + const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + showWarning = linksetPtr->isShowCannotBeVolumeWarning(linksetUse); + } + } + } + + return showWarning; +} + +void LLFloaterPathfindingLinksets::updateStatusMessage() +{ + static const LLColor4 errorColor = LLUIColorTable::instance().getColor("PathfindingErrorColor"); + static const LLColor4 warningColor = LLUIColorTable::instance().getColor("PathfindingWarningColor"); + + std::string statusText(""); + LLStyle::Params styleParams; + + switch (getMessagingState()) + { + case kMessagingUnknown: + statusText = getString("linksets_messaging_initial"); + styleParams.color = errorColor; + break; + case kMessagingGetRequestSent : + statusText = getString("linksets_messaging_get_inprogress"); + styleParams.color = warningColor; + break; + case kMessagingGetError : + statusText = getString("linksets_messaging_get_error"); + styleParams.color = errorColor; + break; + case kMessagingSetRequestSent : + statusText = getString("linksets_messaging_set_inprogress"); + styleParams.color = warningColor; + break; + case kMessagingSetError : + statusText = getString("linksets_messaging_set_error"); + styleParams.color = errorColor; + break; + case kMessagingComplete : + if (mLinksetsScrollList->isEmpty()) + { + statusText = getString("linksets_messaging_complete_none_found"); + } + else + { + S32 numItems = mLinksetsScrollList->getItemCount(); + S32 numSelectedItems = mLinksetsScrollList->getNumSelected(); + + LLLocale locale(LLStringUtil::getLocale()); + std::string numItemsString; + LLResMgr::getInstance()->getIntegerString(numItemsString, numItems); + + std::string numSelectedItemsString; + LLResMgr::getInstance()->getIntegerString(numSelectedItemsString, numSelectedItems); + + LLStringUtil::format_map_t string_args; + string_args["[NUM_SELECTED]"] = numSelectedItemsString; + string_args["[NUM_TOTAL]"] = numItemsString; + statusText = getString("linksets_messaging_complete_available", string_args); + } + break; + case kMessagingNotEnabled : + statusText = getString("linksets_messaging_not_enabled"); + styleParams.color = errorColor; + break; + default: + statusText = getString("linksets_messaging_initial"); + styleParams.color = errorColor; + llassert(0); + break; + } + + mLinksetsStatus->setText((LLStringExplicit)statusText, styleParams); +} + +void LLFloaterPathfindingLinksets::updateEnableStateOnListActions() +{ + switch (getMessagingState()) + { + case kMessagingUnknown: + case kMessagingGetRequestSent : + case kMessagingSetRequestSent : + mRefreshListButton->setEnabled(FALSE); + mSelectAllButton->setEnabled(FALSE); + mSelectNoneButton->setEnabled(FALSE); + break; + case kMessagingGetError : + case kMessagingSetError : + case kMessagingNotEnabled : + mRefreshListButton->setEnabled(TRUE); + mSelectAllButton->setEnabled(FALSE); + mSelectNoneButton->setEnabled(FALSE); + break; + case kMessagingComplete : + { + int numItems = mLinksetsScrollList->getItemCount(); + int numSelectedItems = mLinksetsScrollList->getNumSelected(); + mRefreshListButton->setEnabled(TRUE); + mSelectAllButton->setEnabled(numSelectedItems < numItems); + mSelectNoneButton->setEnabled(numSelectedItems > 0); + } + break; + default: + llassert(0); + break; + } +} + +void LLFloaterPathfindingLinksets::updateEnableStateOnEditFields() +{ + int numSelectedItems = mLinksetsScrollList->getNumSelected(); + bool isEditEnabled = ((numSelectedItems > 0) && LLPathfindingManager::getInstance()->isAllowAlterPermanent()); + + mShowBeaconCheckBox->setEnabled(numSelectedItems > 0); + mTakeButton->setEnabled(isEditEnabled && visible_take_object()); + mTakeCopyButton->setEnabled(isEditEnabled && enable_object_take_copy()); + mReturnButton->setEnabled(isEditEnabled && enable_object_return()); + mDeleteButton->setEnabled(isEditEnabled && enable_object_delete()); + mTeleportButton->setEnabled(numSelectedItems == 1); + + mEditLinksetUse->setEnabled(isEditEnabled); + + mLabelWalkabilityCoefficients->setEnabled(isEditEnabled); + mLabelEditA->setEnabled(isEditEnabled); + mLabelEditB->setEnabled(isEditEnabled); + mLabelEditC->setEnabled(isEditEnabled); + mLabelEditD->setEnabled(isEditEnabled); + mEditA->setEnabled(isEditEnabled); + mEditB->setEnabled(isEditEnabled); + mEditC->setEnabled(isEditEnabled); + mEditD->setEnabled(isEditEnabled); + + mApplyEditsButton->setEnabled(isEditEnabled && (getMessagingState() == kMessagingComplete)); +} + +void LLFloaterPathfindingLinksets::updateEnableStateOnEditLinksetUse() +{ + BOOL useWalkable = FALSE; + BOOL useStaticObstacle = FALSE; + BOOL useDynamicObstacle = FALSE; + BOOL useMaterialVolume = FALSE; + BOOL useExclusionVolume = FALSE; + BOOL useDynamicPhantom = FALSE; + + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); + !(useWalkable && useStaticObstacle && useDynamicObstacle && useMaterialVolume && useExclusionVolume && useDynamicPhantom) && (selectedItemIter != selectedItems.end()); + ++selectedItemIter) + { + const LLScrollListItem *selectedItem = *selectedItemIter; + llassert(mLinksetsListPtr != NULL); + LLPathfindingLinksetList::const_iterator linksetIter = mLinksetsListPtr->find(selectedItem->getUUID().asString()); + llassert(linksetIter != mLinksetsListPtr->end()); + const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + + if (linksetPtr->isTerrain()) + { + useWalkable = TRUE; + } + else + { + if (linksetPtr->isModifiable()) + { + useWalkable = TRUE; + useStaticObstacle = TRUE; + useDynamicObstacle = TRUE; + useDynamicPhantom = TRUE; + if (linksetPtr->canBeVolume()) + { + useMaterialVolume = TRUE; + useExclusionVolume = TRUE; + } + } + else if (linksetPtr->isPhantom()) + { + useDynamicPhantom = TRUE; + if (linksetPtr->canBeVolume()) + { + useMaterialVolume = TRUE; + useExclusionVolume = TRUE; + } + } + else + { + useWalkable = TRUE; + useStaticObstacle = TRUE; + useDynamicObstacle = TRUE; + } + } + } + } + + mEditLinksetUseWalkable->setEnabled(useWalkable); + mEditLinksetUseStaticObstacle->setEnabled(useStaticObstacle); + mEditLinksetUseDynamicObstacle->setEnabled(useDynamicObstacle); + mEditLinksetUseMaterialVolume->setEnabled(useMaterialVolume); + mEditLinksetUseExclusionVolume->setEnabled(useExclusionVolume); + mEditLinksetUseDynamicPhantom->setEnabled(useDynamicPhantom); +} + +void LLFloaterPathfindingLinksets::applyEdit() +{ + LLPathfindingLinkset::ELinksetUse linksetUse = getEditLinksetUse(); + + bool showUnmodifiablePhantomWarning = isShowUnmodifiablePhantomWarning(linksetUse); + bool showCannotBeVolumeWarning = isShowCannotBeVolumeWarning(linksetUse); + + if (showUnmodifiablePhantomWarning || showCannotBeVolumeWarning) + { + LLPathfindingLinkset::ELinksetUse restrictedLinksetUse = LLPathfindingLinkset::getLinksetUseWithToggledPhantom(linksetUse); + LLSD substitutions; + substitutions["REQUESTED_TYPE"] = getLinksetUseString(linksetUse); + substitutions["RESTRICTED_TYPE"] = getLinksetUseString(restrictedLinksetUse); + + std::string notificationName; + if (showUnmodifiablePhantomWarning && showCannotBeVolumeWarning) + { + notificationName = "PathfindingLinksets_SetLinksetUseMismatchOnRestrictedAndVolume"; + } + else if (showUnmodifiablePhantomWarning) + { + notificationName = "PathfindingLinksets_SetLinksetUseMismatchOnRestricted"; + } + else + { + notificationName = "PathfindingLinksets_SetLinksetUseMismatchOnVolume"; + } + LLNotificationsUtil::add(notificationName, substitutions, LLSD(), boost::bind(&LLFloaterPathfindingLinksets::handleApplyEdit, this, _1, _2)); + } + else + { + doApplyEdit(); + } +} + +void LLFloaterPathfindingLinksets::handleApplyEdit(const LLSD &pNotification, const LLSD &pResponse) +{ + if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) + { + doApplyEdit(); + } +} + +void LLFloaterPathfindingLinksets::doApplyEdit() +{ + std::vector selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + LLPathfindingLinkset::ELinksetUse linksetUse = getEditLinksetUse(); + const std::string &aString = mEditA->getText(); + const std::string &bString = mEditB->getText(); + const std::string &cString = mEditC->getText(); + const std::string &dString = mEditD->getText(); + S32 aValue = static_cast(atoi(aString.c_str())); + S32 bValue = static_cast(atoi(bString.c_str())); + S32 cValue = static_cast(atoi(cString.c_str())); + S32 dValue = static_cast(atoi(dString.c_str())); + + LLPathfindingLinksetListPtr editListPtr(new LLPathfindingLinksetList()); + for (std::vector::const_iterator itemIter = selectedItems.begin(); + itemIter != selectedItems.end(); ++itemIter) + { + const LLScrollListItem *listItem = *itemIter; + LLUUID uuid = listItem->getUUID(); + const std::string &uuidString = uuid.asString(); + llassert(mLinksetsListPtr != NULL); + LLPathfindingLinksetList::iterator linksetIter = mLinksetsListPtr->find(uuidString); + llassert(linksetIter != mLinksetsListPtr->end()); + LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + editListPtr->insert(std::pair(uuidString, linksetPtr)); + } + + requestSetLinksets(editListPtr, linksetUse, aValue, bValue, cValue, dValue); + } +} + +std::string LLFloaterPathfindingLinksets::getLinksetUseString(LLPathfindingLinkset::ELinksetUse pLinksetUse) const +{ + std::string linksetUse; + + switch (pLinksetUse) + { + case LLPathfindingLinkset::kWalkable : + linksetUse = getString("linkset_use_walkable"); + break; + case LLPathfindingLinkset::kStaticObstacle : + linksetUse = getString("linkset_use_static_obstacle"); + break; + case LLPathfindingLinkset::kDynamicObstacle : + linksetUse = getString("linkset_use_dynamic_obstacle"); + break; + case LLPathfindingLinkset::kMaterialVolume : + linksetUse = getString("linkset_use_material_volume"); + break; + case LLPathfindingLinkset::kExclusionVolume : + linksetUse = getString("linkset_use_exclusion_volume"); + break; + case LLPathfindingLinkset::kDynamicPhantom : + linksetUse = getString("linkset_use_dynamic_phantom"); + break; + case LLPathfindingLinkset::kUnknown : + default : + linksetUse = getString("linkset_use_dynamic_obstacle"); + llassert(0); + break; + } + + return linksetUse; +} + +LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::getFilterLinksetUse() const +{ + return convertToLinksetUse(mFilterByLinksetUse->getValue()); +} + +void LLFloaterPathfindingLinksets::setFilterLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse) +{ + mFilterByLinksetUse->setValue(convertToXuiValue(pLinksetUse)); +} + +LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::getEditLinksetUse() const +{ + return convertToLinksetUse(mEditLinksetUse->getValue()); +} + +void LLFloaterPathfindingLinksets::setEditLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse) +{ + mEditLinksetUse->setValue(convertToXuiValue(pLinksetUse)); +} + +LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::convertToLinksetUse(LLSD pXuiValue) const +{ + LLPathfindingLinkset::ELinksetUse linkUse; + + switch (pXuiValue.asInteger()) + { + case XUI_LINKSET_USE_NONE : + linkUse = LLPathfindingLinkset::kUnknown; + break; + case XUI_LINKSET_USE_WALKABLE : + linkUse = LLPathfindingLinkset::kWalkable; + break; + case XUI_LINKSET_USE_STATIC_OBSTACLE : + linkUse = LLPathfindingLinkset::kStaticObstacle; + break; + case XUI_LINKSET_USE_DYNAMIC_OBSTACLE : + linkUse = LLPathfindingLinkset::kDynamicObstacle; + break; + case XUI_LINKSET_USE_MATERIAL_VOLUME : + linkUse = LLPathfindingLinkset::kMaterialVolume; + break; + case XUI_LINKSET_USE_EXCLUSION_VOLUME : + linkUse = LLPathfindingLinkset::kExclusionVolume; + break; + case XUI_LINKSET_USE_DYNAMIC_PHANTOM : + linkUse = LLPathfindingLinkset::kDynamicPhantom; + break; + default : + linkUse = LLPathfindingLinkset::kUnknown; + llassert(0); + break; + } + + return linkUse; +} + +LLSD LLFloaterPathfindingLinksets::convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const +{ + LLSD xuiValue; + + switch (pLinksetUse) + { + case LLPathfindingLinkset::kUnknown : + xuiValue = XUI_LINKSET_USE_NONE; + break; + case LLPathfindingLinkset::kWalkable : + xuiValue = XUI_LINKSET_USE_WALKABLE; + break; + case LLPathfindingLinkset::kStaticObstacle : + xuiValue = XUI_LINKSET_USE_STATIC_OBSTACLE; + break; + case LLPathfindingLinkset::kDynamicObstacle : + xuiValue = XUI_LINKSET_USE_DYNAMIC_OBSTACLE; + break; + case LLPathfindingLinkset::kMaterialVolume : + xuiValue = XUI_LINKSET_USE_MATERIAL_VOLUME; + break; + case LLPathfindingLinkset::kExclusionVolume : + xuiValue = XUI_LINKSET_USE_EXCLUSION_VOLUME; + break; + case LLPathfindingLinkset::kDynamicPhantom : + xuiValue = XUI_LINKSET_USE_DYNAMIC_PHANTOM; + break; + default : + xuiValue = XUI_LINKSET_USE_NONE; + llassert(0); + break; + } + + return xuiValue; +} diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h index c3a243314f..0fa4d9aac9 100644 --- a/indra/newview/llfloaterpathfindinglinksets.h +++ b/indra/newview/llfloaterpathfindinglinksets.h @@ -1,184 +1,184 @@ -/** - * @file llfloaterpathfindinglinksets.h - * @author William Todd Stinson - * @brief "Pathfinding linksets" floater, allowing manipulation of the Havok AI pathfinding settings. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERPATHFINDINGLINKSETS_H -#define LL_LLFLOATERPATHFINDINGLINKSETS_H - -#include "llfloater.h" -#include "lluuid.h" -#include "llselectmgr.h" -#include "llpathfindinglinkset.h" -#include "llpathfindinglinksetlist.h" -#include "llpathfindingmanager.h" - -#include - -class LLSD; -class LLUICtrl; -class LLTextBase; -class LLScrollListCtrl; -class LLScrollListItem; -class LLLineEditor; -class LLComboBox; -class LLCheckBoxCtrl; -class LLButton; - -class LLFloaterPathfindingLinksets -: public LLFloater -{ - friend class LLFloaterReg; - -public: - typedef enum - { - kMessagingUnknown, - kMessagingGetRequestSent, - kMessagingGetError, - kMessagingSetRequestSent, - kMessagingSetError, - kMessagingComplete, - kMessagingNotEnabled - } EMessagingState; - - virtual BOOL postBuild(); - virtual void onOpen(const LLSD& pKey); - virtual void onClose(bool pAppQuitting); - virtual void draw(); - - static void openLinksetsEditor(); - -protected: - -private: - LLLineEditor *mFilterByName; - LLLineEditor *mFilterByDescription; - LLComboBox *mFilterByLinksetUse; - LLScrollListCtrl *mLinksetsScrollList; - LLTextBase *mLinksetsStatus; - LLButton *mRefreshListButton; - LLButton *mSelectAllButton; - LLButton *mSelectNoneButton; - LLCheckBoxCtrl *mShowBeaconCheckBox; - LLButton *mTakeButton; - LLButton *mTakeCopyButton; - LLButton *mReturnButton; - LLButton *mDeleteButton; - LLButton *mTeleportButton; - LLComboBox *mEditLinksetUse; - LLScrollListItem *mEditLinksetUseUnset; - LLScrollListItem *mEditLinksetUseWalkable; - LLScrollListItem *mEditLinksetUseStaticObstacle; - LLScrollListItem *mEditLinksetUseDynamicObstacle; - LLScrollListItem *mEditLinksetUseMaterialVolume; - LLScrollListItem *mEditLinksetUseExclusionVolume; - LLScrollListItem *mEditLinksetUseDynamicPhantom; - LLTextBase *mLabelWalkabilityCoefficients; - LLTextBase *mLabelEditA; - LLLineEditor *mEditA; - LLTextBase *mLabelEditB; - LLLineEditor *mEditB; - LLTextBase *mLabelEditC; - LLLineEditor *mEditC; - LLTextBase *mLabelEditD; - LLLineEditor *mEditD; - LLButton *mApplyEditsButton; - - EMessagingState mMessagingState; - LLPathfindingManager::request_id_t mMessagingRequestId; - LLPathfindingLinksetListPtr mLinksetsListPtr; - LLObjectSelectionHandle mLinksetsSelection; - LLPathfindingManager::agent_state_slot_t mAgentStateSlot; - boost::signals2::connection mSelectionUpdateSlot; - boost::signals2::connection mRegionBoundarySlot; - - // Does its own instance management, so clients not allowed - // to allocate or destroy. - LLFloaterPathfindingLinksets(const LLSD& pSeed); - virtual ~LLFloaterPathfindingLinksets(); - - EMessagingState getMessagingState() const; - void setMessagingState(EMessagingState pMessagingState); - - void requestGetLinksets(); - void requestSetLinksets(LLPathfindingLinksetListPtr pLinksetList, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD); - void handleNewLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr); - void handleUpdateLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr); - - void onApplyAllFilters(); - void onClearFiltersClicked(); - void onLinksetsSelectionChange(); - void onRefreshLinksetsClicked(); - void onSelectAllLinksetsClicked(); - void onSelectNoneLinksetsClicked(); - void onTakeClicked(); - void onTakeCopyClicked(); - void onReturnClicked(); - void onDeleteClicked(); - void onTeleportClicked(); - void onWalkabilityCoefficientEntered(LLUICtrl *pUICtrl); - void onApplyChangesClicked(); - void onAgentStateCB(LLPathfindingManager::EAgentState pAgentState); - void onRegionBoundaryCross(); - - void applyFilters(); - void clearFilters(); - - void selectAllLinksets(); - void selectNoneLinksets(); - void clearLinksets(); - - void updateControls(); - void updateEditFieldValues(); - void updateScrollList(); - LLSD buildLinksetScrollListElement(const LLPathfindingLinksetPtr pLinksetPtr, const LLVector3 &pAvatarPosition) const; - LLSD buildLinksetUseScrollListElement(const std::string &label, S32 value) const; - - bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const; - bool isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const; - - void updateStatusMessage(); - void updateEnableStateOnListActions(); - void updateEnableStateOnEditFields(); - void updateEnableStateOnEditLinksetUse(); - - void applyEdit(); - void handleApplyEdit(const LLSD &pNotification, const LLSD &pResponse); - void doApplyEdit(); - - std::string getLinksetUseString(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; - - LLPathfindingLinkset::ELinksetUse getFilterLinksetUse() const; - void setFilterLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse); - - LLPathfindingLinkset::ELinksetUse getEditLinksetUse() const; - void setEditLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse); - - LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const; - LLSD convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; -}; - -#endif // LL_LLFLOATERPATHFINDINGLINKSETS_H +/** + * @file llfloaterpathfindinglinksets.h + * @author William Todd Stinson + * @brief "Pathfinding linksets" floater, allowing manipulation of the Havok AI pathfinding settings. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERPATHFINDINGLINKSETS_H +#define LL_LLFLOATERPATHFINDINGLINKSETS_H + +#include "llfloater.h" +#include "lluuid.h" +#include "llselectmgr.h" +#include "llpathfindinglinkset.h" +#include "llpathfindinglinksetlist.h" +#include "llpathfindingmanager.h" + +#include + +class LLSD; +class LLUICtrl; +class LLTextBase; +class LLScrollListCtrl; +class LLScrollListItem; +class LLLineEditor; +class LLComboBox; +class LLCheckBoxCtrl; +class LLButton; + +class LLFloaterPathfindingLinksets +: public LLFloater +{ + friend class LLFloaterReg; + +public: + typedef enum + { + kMessagingUnknown, + kMessagingGetRequestSent, + kMessagingGetError, + kMessagingSetRequestSent, + kMessagingSetError, + kMessagingComplete, + kMessagingNotEnabled + } EMessagingState; + + virtual BOOL postBuild(); + virtual void onOpen(const LLSD& pKey); + virtual void onClose(bool pAppQuitting); + virtual void draw(); + + static void openLinksetsEditor(); + +protected: + +private: + LLLineEditor *mFilterByName; + LLLineEditor *mFilterByDescription; + LLComboBox *mFilterByLinksetUse; + LLScrollListCtrl *mLinksetsScrollList; + LLTextBase *mLinksetsStatus; + LLButton *mRefreshListButton; + LLButton *mSelectAllButton; + LLButton *mSelectNoneButton; + LLCheckBoxCtrl *mShowBeaconCheckBox; + LLButton *mTakeButton; + LLButton *mTakeCopyButton; + LLButton *mReturnButton; + LLButton *mDeleteButton; + LLButton *mTeleportButton; + LLComboBox *mEditLinksetUse; + LLScrollListItem *mEditLinksetUseUnset; + LLScrollListItem *mEditLinksetUseWalkable; + LLScrollListItem *mEditLinksetUseStaticObstacle; + LLScrollListItem *mEditLinksetUseDynamicObstacle; + LLScrollListItem *mEditLinksetUseMaterialVolume; + LLScrollListItem *mEditLinksetUseExclusionVolume; + LLScrollListItem *mEditLinksetUseDynamicPhantom; + LLTextBase *mLabelWalkabilityCoefficients; + LLTextBase *mLabelEditA; + LLLineEditor *mEditA; + LLTextBase *mLabelEditB; + LLLineEditor *mEditB; + LLTextBase *mLabelEditC; + LLLineEditor *mEditC; + LLTextBase *mLabelEditD; + LLLineEditor *mEditD; + LLButton *mApplyEditsButton; + + EMessagingState mMessagingState; + LLPathfindingManager::request_id_t mMessagingRequestId; + LLPathfindingLinksetListPtr mLinksetsListPtr; + LLObjectSelectionHandle mLinksetsSelection; + LLPathfindingManager::agent_state_slot_t mAgentStateSlot; + boost::signals2::connection mSelectionUpdateSlot; + boost::signals2::connection mRegionBoundarySlot; + + // Does its own instance management, so clients not allowed + // to allocate or destroy. + LLFloaterPathfindingLinksets(const LLSD& pSeed); + virtual ~LLFloaterPathfindingLinksets(); + + EMessagingState getMessagingState() const; + void setMessagingState(EMessagingState pMessagingState); + + void requestGetLinksets(); + void requestSetLinksets(LLPathfindingLinksetListPtr pLinksetList, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD); + void handleNewLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr); + void handleUpdateLinksets(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pLinksetsRequestStatus, LLPathfindingLinksetListPtr pLinksetsListPtr); + + void onApplyAllFilters(); + void onClearFiltersClicked(); + void onLinksetsSelectionChange(); + void onRefreshLinksetsClicked(); + void onSelectAllLinksetsClicked(); + void onSelectNoneLinksetsClicked(); + void onTakeClicked(); + void onTakeCopyClicked(); + void onReturnClicked(); + void onDeleteClicked(); + void onTeleportClicked(); + void onWalkabilityCoefficientEntered(LLUICtrl *pUICtrl); + void onApplyChangesClicked(); + void onAgentStateCB(LLPathfindingManager::EAgentState pAgentState); + void onRegionBoundaryCross(); + + void applyFilters(); + void clearFilters(); + + void selectAllLinksets(); + void selectNoneLinksets(); + void clearLinksets(); + + void updateControls(); + void updateEditFieldValues(); + void updateScrollList(); + LLSD buildLinksetScrollListElement(const LLPathfindingLinksetPtr pLinksetPtr, const LLVector3 &pAvatarPosition) const; + LLSD buildLinksetUseScrollListElement(const std::string &label, S32 value) const; + + bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const; + bool isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse linksetUse) const; + + void updateStatusMessage(); + void updateEnableStateOnListActions(); + void updateEnableStateOnEditFields(); + void updateEnableStateOnEditLinksetUse(); + + void applyEdit(); + void handleApplyEdit(const LLSD &pNotification, const LLSD &pResponse); + void doApplyEdit(); + + std::string getLinksetUseString(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; + + LLPathfindingLinkset::ELinksetUse getFilterLinksetUse() const; + void setFilterLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse); + + LLPathfindingLinkset::ELinksetUse getEditLinksetUse() const; + void setEditLinksetUse(LLPathfindingLinkset::ELinksetUse pLinksetUse); + + LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const; + LLSD convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; +}; + +#endif // LL_LLFLOATERPATHFINDINGLINKSETS_H diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index d277ded636..792d852d53 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -890,12 +890,12 @@ void LLPanelVolume::onCommitIsFlexible(LLUICtrl *, void*) void LLPanelVolume::handleResponseChangeToFlexible(const LLSD &pNotification, const LLSD &pResponse) { - if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) - { - sendIsFlexible(); - } - else - { - getChild("Flexible1D Checkbox Ctrl")->setValue(FALSE); - } + if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) + { + sendIsFlexible(); + } + else + { + getChild("Flexible1D Checkbox Ctrl")->setValue(FALSE); + } } diff --git a/indra/newview/llpathfindingcharacter.cpp b/indra/newview/llpathfindingcharacter.cpp index 4600f661f8..0a3d737b73 100644 --- a/indra/newview/llpathfindingcharacter.cpp +++ b/indra/newview/llpathfindingcharacter.cpp @@ -1,103 +1,103 @@ -/** - * @file llpathfindingcharacter.cpp - * @author William Todd Stinson - * @brief Definition of a pathfinding character that contains various properties required for havok pathfinding. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llpathfindingcharacter.h" -#include "llsd.h" -#include "v3math.h" -#include "lluuid.h" -#include "llavatarname.h" -#include "llavatarnamecache.h" - -#define CHARACTER_NAME_FIELD "name" -#define CHARACTER_DESCRIPTION_FIELD "description" -#define CHARACTER_OWNER_FIELD "owner" -#define CHARACTER_CPU_TIME_FIELD "cpu_time" -#define CHARACTER_POSITION_FIELD "position" - -//--------------------------------------------------------------------------- -// LLPathfindingCharacter -//--------------------------------------------------------------------------- - -LLPathfindingCharacter::LLPathfindingCharacter(const std::string &pUUID, const LLSD& pCharacterItem) - : mUUID(pUUID), - mName(), - mDescription(), - mOwnerUUID(), - mOwnerName(), - mCPUTime(0U), - mLocation(LLVector3::zero) -{ - llassert(pCharacterItem.has(CHARACTER_NAME_FIELD)); - llassert(pCharacterItem.get(CHARACTER_NAME_FIELD).isString()); - mName = pCharacterItem.get(CHARACTER_NAME_FIELD).asString(); - - llassert(pCharacterItem.has(CHARACTER_DESCRIPTION_FIELD)); - llassert(pCharacterItem.get(CHARACTER_DESCRIPTION_FIELD).isString()); - mDescription = pCharacterItem.get(CHARACTER_DESCRIPTION_FIELD).asString(); - - llassert(pCharacterItem.has(CHARACTER_OWNER_FIELD)); - llassert(pCharacterItem.get(CHARACTER_OWNER_FIELD).isUUID()); - mOwnerUUID = pCharacterItem.get(CHARACTER_OWNER_FIELD).asUUID(); - LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); - - llassert(pCharacterItem.has(CHARACTER_CPU_TIME_FIELD)); - llassert(pCharacterItem.get(CHARACTER_CPU_TIME_FIELD).isReal()); - mCPUTime = pCharacterItem.get(CHARACTER_CPU_TIME_FIELD).asReal(); - - llassert(pCharacterItem.has(CHARACTER_POSITION_FIELD)); - llassert(pCharacterItem.get(CHARACTER_POSITION_FIELD).isArray()); - mLocation.setValue(pCharacterItem.get(CHARACTER_POSITION_FIELD)); -} - -LLPathfindingCharacter::LLPathfindingCharacter(const LLPathfindingCharacter& pOther) - : mUUID(pOther.mUUID), - mName(pOther.mName), - mDescription(pOther.mDescription), - mOwnerUUID(pOther.mOwnerUUID), - mOwnerName(pOther.mOwnerName), - mCPUTime(pOther.mCPUTime), - mLocation(pOther.mLocation) -{ -} - -LLPathfindingCharacter::~LLPathfindingCharacter() -{ -} - -LLPathfindingCharacter& LLPathfindingCharacter::operator =(const LLPathfindingCharacter& pOther) -{ - mUUID = pOther.mUUID; - mName = pOther.mName; - mDescription = pOther.mDescription; - mOwnerUUID = pOther.mOwnerUUID; - mOwnerName = pOther.mOwnerName; - mCPUTime = pOther.mCPUTime; - mLocation = pOther.mLocation; - - return *this; -} +/** + * @file llpathfindingcharacter.cpp + * @author William Todd Stinson + * @brief Definition of a pathfinding character that contains various properties required for havok pathfinding. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llpathfindingcharacter.h" +#include "llsd.h" +#include "v3math.h" +#include "lluuid.h" +#include "llavatarname.h" +#include "llavatarnamecache.h" + +#define CHARACTER_NAME_FIELD "name" +#define CHARACTER_DESCRIPTION_FIELD "description" +#define CHARACTER_OWNER_FIELD "owner" +#define CHARACTER_CPU_TIME_FIELD "cpu_time" +#define CHARACTER_POSITION_FIELD "position" + +//--------------------------------------------------------------------------- +// LLPathfindingCharacter +//--------------------------------------------------------------------------- + +LLPathfindingCharacter::LLPathfindingCharacter(const std::string &pUUID, const LLSD& pCharacterItem) + : mUUID(pUUID), + mName(), + mDescription(), + mOwnerUUID(), + mOwnerName(), + mCPUTime(0U), + mLocation(LLVector3::zero) +{ + llassert(pCharacterItem.has(CHARACTER_NAME_FIELD)); + llassert(pCharacterItem.get(CHARACTER_NAME_FIELD).isString()); + mName = pCharacterItem.get(CHARACTER_NAME_FIELD).asString(); + + llassert(pCharacterItem.has(CHARACTER_DESCRIPTION_FIELD)); + llassert(pCharacterItem.get(CHARACTER_DESCRIPTION_FIELD).isString()); + mDescription = pCharacterItem.get(CHARACTER_DESCRIPTION_FIELD).asString(); + + llassert(pCharacterItem.has(CHARACTER_OWNER_FIELD)); + llassert(pCharacterItem.get(CHARACTER_OWNER_FIELD).isUUID()); + mOwnerUUID = pCharacterItem.get(CHARACTER_OWNER_FIELD).asUUID(); + LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); + + llassert(pCharacterItem.has(CHARACTER_CPU_TIME_FIELD)); + llassert(pCharacterItem.get(CHARACTER_CPU_TIME_FIELD).isReal()); + mCPUTime = pCharacterItem.get(CHARACTER_CPU_TIME_FIELD).asReal(); + + llassert(pCharacterItem.has(CHARACTER_POSITION_FIELD)); + llassert(pCharacterItem.get(CHARACTER_POSITION_FIELD).isArray()); + mLocation.setValue(pCharacterItem.get(CHARACTER_POSITION_FIELD)); +} + +LLPathfindingCharacter::LLPathfindingCharacter(const LLPathfindingCharacter& pOther) + : mUUID(pOther.mUUID), + mName(pOther.mName), + mDescription(pOther.mDescription), + mOwnerUUID(pOther.mOwnerUUID), + mOwnerName(pOther.mOwnerName), + mCPUTime(pOther.mCPUTime), + mLocation(pOther.mLocation) +{ +} + +LLPathfindingCharacter::~LLPathfindingCharacter() +{ +} + +LLPathfindingCharacter& LLPathfindingCharacter::operator =(const LLPathfindingCharacter& pOther) +{ + mUUID = pOther.mUUID; + mName = pOther.mName; + mDescription = pOther.mDescription; + mOwnerUUID = pOther.mOwnerUUID; + mOwnerName = pOther.mOwnerName; + mCPUTime = pOther.mCPUTime; + mLocation = pOther.mLocation; + + return *this; +} diff --git a/indra/newview/llpathfindingcharacter.h b/indra/newview/llpathfindingcharacter.h index 5be52ebc45..3e40343831 100644 --- a/indra/newview/llpathfindingcharacter.h +++ b/indra/newview/llpathfindingcharacter.h @@ -1,70 +1,70 @@ -/** - * @file llpathfindingcharacter.h - * @author William Todd Stinson - * @brief Definition of a pathfinding character that contains various properties required for havok pathfinding. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPATHFINDINGCHARACTER_H -#define LL_LLPATHFINDINGCHARACTER_H - -#include "v3math.h" -#include "lluuid.h" -#include "llavatarname.h" - -#include - -class LLSD; -class LLPathfindingCharacter; - -typedef boost::shared_ptr LLPathfindingCharacterPtr; - -class LLPathfindingCharacter -{ -public: - LLPathfindingCharacter(const std::string &pUUID, const LLSD &pCharacterItem); - LLPathfindingCharacter(const LLPathfindingCharacter& pOther); - virtual ~LLPathfindingCharacter(); - - LLPathfindingCharacter& operator = (const LLPathfindingCharacter& pOther); - - inline const LLUUID& getUUID() const {return mUUID;}; - inline const std::string& getName() const {return mName;}; - inline const std::string& getDescription() const {return mDescription;}; - inline const std::string getOwnerName() const {return mOwnerName.getCompleteName();}; - inline F32 getCPUTime() const {return mCPUTime;}; - inline const LLVector3& getLocation() const {return mLocation;}; - -protected: - -private: - LLUUID mUUID; - std::string mName; - std::string mDescription; - LLUUID mOwnerUUID; - LLAvatarName mOwnerName; - F32 mCPUTime; - LLVector3 mLocation; -}; - -#endif // LL_LLPATHFINDINGCHARACTER_H +/** + * @file llpathfindingcharacter.h + * @author William Todd Stinson + * @brief Definition of a pathfinding character that contains various properties required for havok pathfinding. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPATHFINDINGCHARACTER_H +#define LL_LLPATHFINDINGCHARACTER_H + +#include "v3math.h" +#include "lluuid.h" +#include "llavatarname.h" + +#include + +class LLSD; +class LLPathfindingCharacter; + +typedef boost::shared_ptr LLPathfindingCharacterPtr; + +class LLPathfindingCharacter +{ +public: + LLPathfindingCharacter(const std::string &pUUID, const LLSD &pCharacterItem); + LLPathfindingCharacter(const LLPathfindingCharacter& pOther); + virtual ~LLPathfindingCharacter(); + + LLPathfindingCharacter& operator = (const LLPathfindingCharacter& pOther); + + inline const LLUUID& getUUID() const {return mUUID;}; + inline const std::string& getName() const {return mName;}; + inline const std::string& getDescription() const {return mDescription;}; + inline const std::string getOwnerName() const {return mOwnerName.getCompleteName();}; + inline F32 getCPUTime() const {return mCPUTime;}; + inline const LLVector3& getLocation() const {return mLocation;}; + +protected: + +private: + LLUUID mUUID; + std::string mName; + std::string mDescription; + LLUUID mOwnerUUID; + LLAvatarName mOwnerName; + F32 mCPUTime; + LLVector3 mLocation; +}; + +#endif // LL_LLPATHFINDINGCHARACTER_H diff --git a/indra/newview/llpathfindingcharacterlist.cpp b/indra/newview/llpathfindingcharacterlist.cpp index 64fddd490c..5ab4a8910f 100644 --- a/indra/newview/llpathfindingcharacterlist.cpp +++ b/indra/newview/llpathfindingcharacterlist.cpp @@ -1,63 +1,63 @@ -/** - * @file llpathfindingcharacterlist.cpp - * @author William Todd Stinson - * @brief Class to implement the list of a set of pathfinding characters - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include -#include - -#include "llsd.h" -#include "lluuid.h" -#include "llpathfindingcharacter.h" -#include "llpathfindingcharacterlist.h" - -//--------------------------------------------------------------------------- -// LLPathfindingCharacterList -//--------------------------------------------------------------------------- - -LLPathfindingCharacterList::LLPathfindingCharacterList() - : LLPathfindingCharacterMap() -{ -} - -LLPathfindingCharacterList::LLPathfindingCharacterList(const LLSD& pCharacterItems) - : LLPathfindingCharacterMap() -{ - for (LLSD::map_const_iterator characterItemIter = pCharacterItems.beginMap(); - characterItemIter != pCharacterItems.endMap(); ++characterItemIter) - { - const std::string& uuid(characterItemIter->first); - const LLSD& characterData = characterItemIter->second; - LLPathfindingCharacterPtr character(new LLPathfindingCharacter(uuid, characterData)); - insert(std::pair(uuid, character)); - } -} - -LLPathfindingCharacterList::~LLPathfindingCharacterList() -{ - clear(); -} +/** + * @file llpathfindingcharacterlist.cpp + * @author William Todd Stinson + * @brief Class to implement the list of a set of pathfinding characters + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include +#include + +#include "llsd.h" +#include "lluuid.h" +#include "llpathfindingcharacter.h" +#include "llpathfindingcharacterlist.h" + +//--------------------------------------------------------------------------- +// LLPathfindingCharacterList +//--------------------------------------------------------------------------- + +LLPathfindingCharacterList::LLPathfindingCharacterList() + : LLPathfindingCharacterMap() +{ +} + +LLPathfindingCharacterList::LLPathfindingCharacterList(const LLSD& pCharacterItems) + : LLPathfindingCharacterMap() +{ + for (LLSD::map_const_iterator characterItemIter = pCharacterItems.beginMap(); + characterItemIter != pCharacterItems.endMap(); ++characterItemIter) + { + const std::string& uuid(characterItemIter->first); + const LLSD& characterData = characterItemIter->second; + LLPathfindingCharacterPtr character(new LLPathfindingCharacter(uuid, characterData)); + insert(std::pair(uuid, character)); + } +} + +LLPathfindingCharacterList::~LLPathfindingCharacterList() +{ + clear(); +} diff --git a/indra/newview/llpathfindingcharacterlist.h b/indra/newview/llpathfindingcharacterlist.h index ce6ec81615..601c89626d 100644 --- a/indra/newview/llpathfindingcharacterlist.h +++ b/indra/newview/llpathfindingcharacterlist.h @@ -1,56 +1,56 @@ -/** - * @file llpathfindingcharacterlist.h - * @author William Todd Stinson - * @brief Class to implement the list of a set of pathfinding characters - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPATHFINDINGCHARACTERLIST_H -#define LL_LLPATHFINDINGCHARACTERLIST_H - -#include -#include -#include "llpathfindingcharacter.h" - -#include - -class LLSD; -class LLPathfindingCharacterList; - -typedef boost::shared_ptr LLPathfindingCharacterListPtr; -typedef std::map LLPathfindingCharacterMap; - -class LLPathfindingCharacterList : public LLPathfindingCharacterMap -{ -public: - LLPathfindingCharacterList(); - LLPathfindingCharacterList(const LLSD& pCharacterItems); - virtual ~LLPathfindingCharacterList(); - -protected: - -private: - -}; - -#endif // LL_LLPATHFINDINGCHARACTERLIST_H +/** + * @file llpathfindingcharacterlist.h + * @author William Todd Stinson + * @brief Class to implement the list of a set of pathfinding characters + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPATHFINDINGCHARACTERLIST_H +#define LL_LLPATHFINDINGCHARACTERLIST_H + +#include +#include +#include "llpathfindingcharacter.h" + +#include + +class LLSD; +class LLPathfindingCharacterList; + +typedef boost::shared_ptr LLPathfindingCharacterListPtr; +typedef std::map LLPathfindingCharacterMap; + +class LLPathfindingCharacterList : public LLPathfindingCharacterMap +{ +public: + LLPathfindingCharacterList(); + LLPathfindingCharacterList(const LLSD& pCharacterItems); + virtual ~LLPathfindingCharacterList(); + +protected: + +private: + +}; + +#endif // LL_LLPATHFINDINGCHARACTERLIST_H diff --git a/indra/newview/llpathfindinglinkset.cpp b/indra/newview/llpathfindinglinkset.cpp index f2d95d9221..e7478870ca 100644 --- a/indra/newview/llpathfindinglinkset.cpp +++ b/indra/newview/llpathfindinglinkset.cpp @@ -1,522 +1,522 @@ -/** - * @file llpathfindinglinksets.cpp - * @author William Todd Stinson - * @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llpathfindinglinkset.h" -#include "llsd.h" -#include "v3math.h" -#include "lluuid.h" - -#define LINKSET_NAME_FIELD "name" -#define LINKSET_DESCRIPTION_FIELD "description" -#define LINKSET_LAND_IMPACT_FIELD "landimpact" -#define LINKSET_MODIFIABLE_FIELD "modifiable" -#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS -#define DEPRECATED_LINKSET_PERMANENT_FIELD "permanent" -#define DEPRECATED_LINKSET_WALKABLE_FIELD "walkable" -#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS -#define LINKSET_CATEGORY_FIELD "navmesh_category" -#define LINKSET_CAN_BE_VOLUME "can_be_volume" -#define LINKSET_PHANTOM_FIELD "phantom" -#define LINKSET_WALKABILITY_A_FIELD "A" -#define LINKSET_WALKABILITY_B_FIELD "B" -#define LINKSET_WALKABILITY_C_FIELD "C" -#define LINKSET_WALKABILITY_D_FIELD "D" -#define LINKSET_POSITION_FIELD "position" - -#define LINKSET_CATEGORY_VALUE_INCLUDE 0 -#define LINKSET_CATEGORY_VALUE_EXCLUDE 1 -#define LINKSET_CATEGORY_VALUE_IGNORE 2 - -//--------------------------------------------------------------------------- -// LLPathfindingLinkset -//--------------------------------------------------------------------------- - -const S32 LLPathfindingLinkset::MIN_WALKABILITY_VALUE(0); -const S32 LLPathfindingLinkset::MAX_WALKABILITY_VALUE(100); - -LLPathfindingLinkset::LLPathfindingLinkset(const LLSD& pTerrainLinksetItem) - : mUUID(), - mIsTerrain(true), - mName(), - mDescription(), - mLandImpact(0U), - mLocation(LLVector3::zero), -#ifdef MISSING_MODIFIABLE_FIELD_WAR - mHasModifiable(true), -#endif // MISSING_MODIFIABLE_FIELD_WAR - mIsModifiable(FALSE), - mCanBeVolume(FALSE), - mLinksetUse(kUnknown), - mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), - mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), - mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE), - mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE) -{ - parsePathfindingData(pTerrainLinksetItem); -} - -LLPathfindingLinkset::LLPathfindingLinkset(const std::string &pUUID, const LLSD& pLinksetItem) - : mUUID(pUUID), - mIsTerrain(false), - mName(), - mDescription(), - mLandImpact(0U), - mLocation(LLVector3::zero), -#ifdef MISSING_MODIFIABLE_FIELD_WAR - mHasModifiable(false), -#endif // MISSING_MODIFIABLE_FIELD_WAR - mIsModifiable(TRUE), - mCanBeVolume(TRUE), - mLinksetUse(kUnknown), - mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), - mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), - mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE), - mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE) -{ - parseObjectData(pLinksetItem); - parsePathfindingData(pLinksetItem); -} - -LLPathfindingLinkset::LLPathfindingLinkset(const LLPathfindingLinkset& pOther) - : mUUID(pOther.mUUID), - mName(pOther.mName), - mDescription(pOther.mDescription), - mLandImpact(pOther.mLandImpact), - mLocation(pOther.mLocation), -#ifdef MISSING_MODIFIABLE_FIELD_WAR - mHasModifiable(pOther.mHasModifiable), - mIsModifiable(pOther.mHasModifiable ? pOther.mIsModifiable : TRUE), -#else // MISSING_MODIFIABLE_FIELD_WAR - mIsModifiable(pOther.mIsModifiable), -#endif // MISSING_MODIFIABLE_FIELD_WAR - mCanBeVolume(pOther.mCanBeVolume), - mLinksetUse(pOther.mLinksetUse), - mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA), - mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB), - mWalkabilityCoefficientC(pOther.mWalkabilityCoefficientC), - mWalkabilityCoefficientD(pOther.mWalkabilityCoefficientD) -{ -} - -LLPathfindingLinkset::~LLPathfindingLinkset() -{ -} - -LLPathfindingLinkset& LLPathfindingLinkset::operator =(const LLPathfindingLinkset& pOther) -{ - mUUID = pOther.mUUID; - mName = pOther.mName; - mDescription = pOther.mDescription; - mLandImpact = pOther.mLandImpact; - mLocation = pOther.mLocation; -#ifdef MISSING_MODIFIABLE_FIELD_WAR - if (pOther.mHasModifiable) - { - mHasModifiable = pOther.mHasModifiable; - mIsModifiable = pOther.mIsModifiable; - } -#else // MISSING_MODIFIABLE_FIELD_WAR - mIsModifiable = pOther.mIsModifiable; -#endif // MISSING_MODIFIABLE_FIELD_WAR - mCanBeVolume = pOther.mCanBeVolume; - mLinksetUse = pOther.mLinksetUse; - mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA; - mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB; - mWalkabilityCoefficientC = pOther.mWalkabilityCoefficientC; - mWalkabilityCoefficientD = pOther.mWalkabilityCoefficientD; - - return *this; -} - -BOOL LLPathfindingLinkset::isPhantom() const -{ - return isPhantom(getLinksetUse()); -} - -LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUseWithToggledPhantom(ELinksetUse pLinksetUse) -{ - BOOL isPhantom = LLPathfindingLinkset::isPhantom(pLinksetUse); - ENavMeshGenerationCategory navMeshGenerationCategory = getNavMeshGenerationCategory(pLinksetUse); - - return getLinksetUse(!isPhantom, navMeshGenerationCategory); -} - -bool LLPathfindingLinkset::isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const -{ - return (!isModifiable() && (isPhantom() != isPhantom(pLinksetUse))); -} - -bool LLPathfindingLinkset::isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const -{ - return (!canBeVolume() && ((pLinksetUse == kMaterialVolume) || (pLinksetUse == kExclusionVolume))); -} - -LLSD LLPathfindingLinkset::encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const -{ - LLSD itemData; - - if (!isTerrain() && (pLinksetUse != kUnknown) && (getLinksetUse() != pLinksetUse) && - (canBeVolume() || ((pLinksetUse != kMaterialVolume) && (pLinksetUse != kExclusionVolume)))) - { - if (isModifiable()) - { - itemData[LINKSET_PHANTOM_FIELD] = static_cast(isPhantom(pLinksetUse)); - } - -#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - itemData[DEPRECATED_LINKSET_PERMANENT_FIELD] = static_cast(isPermanent(pLinksetUse)); - itemData[DEPRECATED_LINKSET_WALKABLE_FIELD] = static_cast(isWalkable(pLinksetUse)); -#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - itemData[LINKSET_CATEGORY_FIELD] = convertCategoryToLLSD(getNavMeshGenerationCategory(pLinksetUse)); - } - - if (mWalkabilityCoefficientA != pA) - { - itemData[LINKSET_WALKABILITY_A_FIELD] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); - } - - if (mWalkabilityCoefficientB != pB) - { - itemData[LINKSET_WALKABILITY_B_FIELD] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); - } - - if (mWalkabilityCoefficientC != pC) - { - itemData[LINKSET_WALKABILITY_C_FIELD] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); - } - - if (mWalkabilityCoefficientD != pD) - { - itemData[LINKSET_WALKABILITY_D_FIELD] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); - } - - return itemData; -} - -void LLPathfindingLinkset::parseObjectData(const LLSD &pLinksetItem) -{ - llassert(pLinksetItem.has(LINKSET_NAME_FIELD)); - llassert(pLinksetItem.get(LINKSET_NAME_FIELD).isString()); - mName = pLinksetItem.get(LINKSET_NAME_FIELD).asString(); - - llassert(pLinksetItem.has(LINKSET_DESCRIPTION_FIELD)); - llassert(pLinksetItem.get(LINKSET_DESCRIPTION_FIELD).isString()); - mDescription = pLinksetItem.get(LINKSET_DESCRIPTION_FIELD).asString(); - - llassert(pLinksetItem.has(LINKSET_LAND_IMPACT_FIELD)); - llassert(pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).isInteger()); - llassert(pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).asInteger() >= 0); - mLandImpact = pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).asInteger(); - -#ifdef MISSING_MODIFIABLE_FIELD_WAR - mHasModifiable = pLinksetItem.has(LINKSET_MODIFIABLE_FIELD); - if (mHasModifiable) - { - llassert(pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); - mIsModifiable = pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); - } -#else // MISSING_MODIFIABLE_FIELD_WAR - llassert(pLinksetItem.has(LINKSET_MODIFIABLE_FIELD)); - llassert(pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); - mIsModifiable = pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); -#endif // MISSING_MODIFIABLE_FIELD_WAR - - llassert(pLinksetItem.has(LINKSET_POSITION_FIELD)); - llassert(pLinksetItem.get(LINKSET_POSITION_FIELD).isArray()); - mLocation.setValue(pLinksetItem.get(LINKSET_POSITION_FIELD)); -} - -void LLPathfindingLinkset::parsePathfindingData(const LLSD &pLinksetItem) -{ - bool isPhantom = false; - if (pLinksetItem.has(LINKSET_PHANTOM_FIELD)) - { - llassert(pLinksetItem.get(LINKSET_PHANTOM_FIELD).isBoolean()); - isPhantom = pLinksetItem.get(LINKSET_PHANTOM_FIELD).asBoolean(); - } - -#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - if (pLinksetItem.has(LINKSET_CATEGORY_FIELD)) - { - mLinksetUse = getLinksetUse(isPhantom, convertCategoryFromLLSD(pLinksetItem.get(LINKSET_CATEGORY_FIELD))); - } - else - { - llassert(pLinksetItem.has(DEPRECATED_LINKSET_PERMANENT_FIELD)); - llassert(pLinksetItem.get(DEPRECATED_LINKSET_PERMANENT_FIELD).isBoolean()); - bool isPermanent = pLinksetItem.get(DEPRECATED_LINKSET_PERMANENT_FIELD).asBoolean(); - - llassert(pLinksetItem.has(DEPRECATED_LINKSET_WALKABLE_FIELD)); - llassert(pLinksetItem.get(DEPRECATED_LINKSET_WALKABLE_FIELD).isBoolean()); - bool isWalkable = pLinksetItem.get(DEPRECATED_LINKSET_WALKABLE_FIELD).asBoolean(); - - mLinksetUse = getLinksetUse(isPhantom, isPermanent, isWalkable); - } -#else // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - llassert(pLinksetItem.has(LINKSET_CATEGORY_FIELD)); - mLinksetUse = getLinksetUse(isPhantom, convertCategoryFromLLSD(pLinksetItem.get(LINKSET_CATEGORY_FIELD))); -#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - - if (pLinksetItem.has(LINKSET_CAN_BE_VOLUME)) - { - llassert(pLinksetItem.get(LINKSET_CAN_BE_VOLUME).isBoolean()); - mCanBeVolume = pLinksetItem.get(LINKSET_CAN_BE_VOLUME).asBoolean(); - } - - llassert(pLinksetItem.has(LINKSET_WALKABILITY_A_FIELD)); - llassert(pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).isInteger()); - mWalkabilityCoefficientA = pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).asInteger(); - llassert(mWalkabilityCoefficientA >= MIN_WALKABILITY_VALUE); - llassert(mWalkabilityCoefficientA <= MAX_WALKABILITY_VALUE); - - llassert(pLinksetItem.has(LINKSET_WALKABILITY_B_FIELD)); - llassert(pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).isInteger()); - mWalkabilityCoefficientB = pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).asInteger(); - llassert(mWalkabilityCoefficientB >= MIN_WALKABILITY_VALUE); - llassert(mWalkabilityCoefficientB <= MAX_WALKABILITY_VALUE); - - llassert(pLinksetItem.has(LINKSET_WALKABILITY_C_FIELD)); - llassert(pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).isInteger()); - mWalkabilityCoefficientC = pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).asInteger(); - llassert(mWalkabilityCoefficientC >= MIN_WALKABILITY_VALUE); - llassert(mWalkabilityCoefficientC <= MAX_WALKABILITY_VALUE); - - llassert(pLinksetItem.has(LINKSET_WALKABILITY_D_FIELD)); - llassert(pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).isInteger()); - mWalkabilityCoefficientD = pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).asInteger(); - llassert(mWalkabilityCoefficientD >= MIN_WALKABILITY_VALUE); - llassert(mWalkabilityCoefficientD <= MAX_WALKABILITY_VALUE); -} - -#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS -LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUse(bool pIsPhantom, bool pIsPermanent, bool pIsWalkable) -{ - return (pIsPhantom ? (pIsPermanent ? (pIsWalkable ? kMaterialVolume : kExclusionVolume) : kDynamicPhantom) : - (pIsPermanent ? (pIsWalkable ? kWalkable : kStaticObstacle) : kDynamicObstacle)); -} - -BOOL LLPathfindingLinkset::isPermanent(ELinksetUse pLinksetUse) -{ - BOOL retVal; - - switch (pLinksetUse) - { - case kWalkable : - case kStaticObstacle : - case kMaterialVolume : - case kExclusionVolume : - retVal = true; - break; - case kDynamicObstacle : - case kDynamicPhantom : - retVal = false; - break; - case kUnknown : - default : - retVal = false; - llassert(0); - break; - } - - return retVal; -} - -BOOL LLPathfindingLinkset::isWalkable(ELinksetUse pLinksetUse) -{ - BOOL retVal; - - switch (pLinksetUse) - { - case kWalkable : - case kMaterialVolume : - retVal = true; - break; - case kStaticObstacle : - case kDynamicObstacle : - case kExclusionVolume : - case kDynamicPhantom : - retVal = false; - break; - case kUnknown : - default : - retVal = false; - llassert(0); - break; - } - - return retVal; -} -#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - -BOOL LLPathfindingLinkset::isPhantom(ELinksetUse pLinksetUse) -{ - BOOL retVal; - - switch (pLinksetUse) - { - case kWalkable : - case kStaticObstacle : - case kDynamicObstacle : - retVal = false; - break; - case kMaterialVolume : - case kExclusionVolume : - case kDynamicPhantom : - retVal = true; - break; - case kUnknown : - default : - retVal = false; - llassert(0); - break; - } - - return retVal; -} - -LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUse(bool pIsPhantom, ENavMeshGenerationCategory pNavMeshGenerationCategory) -{ - ELinksetUse linksetUse = kUnknown; - - if (pIsPhantom) - { - switch (pNavMeshGenerationCategory) - { - case kNavMeshGenerationIgnore : - linksetUse = kDynamicPhantom; - break; - case kNavMeshGenerationInclude : - linksetUse = kMaterialVolume; - break; - case kNavMeshGenerationExclude : - linksetUse = kExclusionVolume; - break; - default : - linksetUse = kUnknown; - llassert(0); - break; - } - } - else - { - switch (pNavMeshGenerationCategory) - { - case kNavMeshGenerationIgnore : - linksetUse = kDynamicObstacle; - break; - case kNavMeshGenerationInclude : - linksetUse = kWalkable; - break; - case kNavMeshGenerationExclude : - linksetUse = kStaticObstacle; - break; - default : - linksetUse = kUnknown; - llassert(0); - break; - } - } - - return linksetUse; -} - -LLPathfindingLinkset::ENavMeshGenerationCategory LLPathfindingLinkset::getNavMeshGenerationCategory(ELinksetUse pLinksetUse) -{ - ENavMeshGenerationCategory navMeshGenerationCategory; - switch (pLinksetUse) - { - case kWalkable : - case kMaterialVolume : - navMeshGenerationCategory = kNavMeshGenerationInclude; - break; - case kStaticObstacle : - case kExclusionVolume : - navMeshGenerationCategory = kNavMeshGenerationExclude; - break; - case kDynamicObstacle : - case kDynamicPhantom : - navMeshGenerationCategory = kNavMeshGenerationIgnore; - break; - case kUnknown : - default : - navMeshGenerationCategory = kNavMeshGenerationIgnore; - llassert(0); - break; - } - - return navMeshGenerationCategory; -} - -LLSD LLPathfindingLinkset::convertCategoryToLLSD(ENavMeshGenerationCategory pNavMeshGenerationCategory) -{ - LLSD llsd; - - switch (pNavMeshGenerationCategory) - { - case kNavMeshGenerationIgnore : - llsd = static_cast(LINKSET_CATEGORY_VALUE_IGNORE); - break; - case kNavMeshGenerationInclude : - llsd = static_cast(LINKSET_CATEGORY_VALUE_INCLUDE); - break; - case kNavMeshGenerationExclude : - llsd = static_cast(LINKSET_CATEGORY_VALUE_EXCLUDE); - break; - default : - llsd = static_cast(LINKSET_CATEGORY_VALUE_IGNORE); - llassert(0); - break; - } - - return llsd; -} - -LLPathfindingLinkset::ENavMeshGenerationCategory LLPathfindingLinkset::convertCategoryFromLLSD(const LLSD &llsd) -{ - ENavMeshGenerationCategory navMeshGenerationCategory; - - llassert(llsd.isInteger()); - switch (llsd.asInteger()) - { - case LINKSET_CATEGORY_VALUE_IGNORE : - navMeshGenerationCategory = kNavMeshGenerationIgnore; - break; - case LINKSET_CATEGORY_VALUE_INCLUDE : - navMeshGenerationCategory = kNavMeshGenerationInclude; - break; - case LINKSET_CATEGORY_VALUE_EXCLUDE : - navMeshGenerationCategory = kNavMeshGenerationExclude; - break; - default : - navMeshGenerationCategory = kNavMeshGenerationIgnore; - llassert(0); - break; - } - - return navMeshGenerationCategory; -} +/** + * @file llpathfindinglinksets.cpp + * @author William Todd Stinson + * @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llpathfindinglinkset.h" +#include "llsd.h" +#include "v3math.h" +#include "lluuid.h" + +#define LINKSET_NAME_FIELD "name" +#define LINKSET_DESCRIPTION_FIELD "description" +#define LINKSET_LAND_IMPACT_FIELD "landimpact" +#define LINKSET_MODIFIABLE_FIELD "modifiable" +#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS +#define DEPRECATED_LINKSET_PERMANENT_FIELD "permanent" +#define DEPRECATED_LINKSET_WALKABLE_FIELD "walkable" +#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS +#define LINKSET_CATEGORY_FIELD "navmesh_category" +#define LINKSET_CAN_BE_VOLUME "can_be_volume" +#define LINKSET_PHANTOM_FIELD "phantom" +#define LINKSET_WALKABILITY_A_FIELD "A" +#define LINKSET_WALKABILITY_B_FIELD "B" +#define LINKSET_WALKABILITY_C_FIELD "C" +#define LINKSET_WALKABILITY_D_FIELD "D" +#define LINKSET_POSITION_FIELD "position" + +#define LINKSET_CATEGORY_VALUE_INCLUDE 0 +#define LINKSET_CATEGORY_VALUE_EXCLUDE 1 +#define LINKSET_CATEGORY_VALUE_IGNORE 2 + +//--------------------------------------------------------------------------- +// LLPathfindingLinkset +//--------------------------------------------------------------------------- + +const S32 LLPathfindingLinkset::MIN_WALKABILITY_VALUE(0); +const S32 LLPathfindingLinkset::MAX_WALKABILITY_VALUE(100); + +LLPathfindingLinkset::LLPathfindingLinkset(const LLSD& pTerrainLinksetItem) + : mUUID(), + mIsTerrain(true), + mName(), + mDescription(), + mLandImpact(0U), + mLocation(LLVector3::zero), +#ifdef MISSING_MODIFIABLE_FIELD_WAR + mHasModifiable(true), +#endif // MISSING_MODIFIABLE_FIELD_WAR + mIsModifiable(FALSE), + mCanBeVolume(FALSE), + mLinksetUse(kUnknown), + mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE) +{ + parsePathfindingData(pTerrainLinksetItem); +} + +LLPathfindingLinkset::LLPathfindingLinkset(const std::string &pUUID, const LLSD& pLinksetItem) + : mUUID(pUUID), + mIsTerrain(false), + mName(), + mDescription(), + mLandImpact(0U), + mLocation(LLVector3::zero), +#ifdef MISSING_MODIFIABLE_FIELD_WAR + mHasModifiable(false), +#endif // MISSING_MODIFIABLE_FIELD_WAR + mIsModifiable(TRUE), + mCanBeVolume(TRUE), + mLinksetUse(kUnknown), + mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE) +{ + parseObjectData(pLinksetItem); + parsePathfindingData(pLinksetItem); +} + +LLPathfindingLinkset::LLPathfindingLinkset(const LLPathfindingLinkset& pOther) + : mUUID(pOther.mUUID), + mName(pOther.mName), + mDescription(pOther.mDescription), + mLandImpact(pOther.mLandImpact), + mLocation(pOther.mLocation), +#ifdef MISSING_MODIFIABLE_FIELD_WAR + mHasModifiable(pOther.mHasModifiable), + mIsModifiable(pOther.mHasModifiable ? pOther.mIsModifiable : TRUE), +#else // MISSING_MODIFIABLE_FIELD_WAR + mIsModifiable(pOther.mIsModifiable), +#endif // MISSING_MODIFIABLE_FIELD_WAR + mCanBeVolume(pOther.mCanBeVolume), + mLinksetUse(pOther.mLinksetUse), + mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA), + mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB), + mWalkabilityCoefficientC(pOther.mWalkabilityCoefficientC), + mWalkabilityCoefficientD(pOther.mWalkabilityCoefficientD) +{ +} + +LLPathfindingLinkset::~LLPathfindingLinkset() +{ +} + +LLPathfindingLinkset& LLPathfindingLinkset::operator =(const LLPathfindingLinkset& pOther) +{ + mUUID = pOther.mUUID; + mName = pOther.mName; + mDescription = pOther.mDescription; + mLandImpact = pOther.mLandImpact; + mLocation = pOther.mLocation; +#ifdef MISSING_MODIFIABLE_FIELD_WAR + if (pOther.mHasModifiable) + { + mHasModifiable = pOther.mHasModifiable; + mIsModifiable = pOther.mIsModifiable; + } +#else // MISSING_MODIFIABLE_FIELD_WAR + mIsModifiable = pOther.mIsModifiable; +#endif // MISSING_MODIFIABLE_FIELD_WAR + mCanBeVolume = pOther.mCanBeVolume; + mLinksetUse = pOther.mLinksetUse; + mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA; + mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB; + mWalkabilityCoefficientC = pOther.mWalkabilityCoefficientC; + mWalkabilityCoefficientD = pOther.mWalkabilityCoefficientD; + + return *this; +} + +BOOL LLPathfindingLinkset::isPhantom() const +{ + return isPhantom(getLinksetUse()); +} + +LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUseWithToggledPhantom(ELinksetUse pLinksetUse) +{ + BOOL isPhantom = LLPathfindingLinkset::isPhantom(pLinksetUse); + ENavMeshGenerationCategory navMeshGenerationCategory = getNavMeshGenerationCategory(pLinksetUse); + + return getLinksetUse(!isPhantom, navMeshGenerationCategory); +} + +bool LLPathfindingLinkset::isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const +{ + return (!isModifiable() && (isPhantom() != isPhantom(pLinksetUse))); +} + +bool LLPathfindingLinkset::isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const +{ + return (!canBeVolume() && ((pLinksetUse == kMaterialVolume) || (pLinksetUse == kExclusionVolume))); +} + +LLSD LLPathfindingLinkset::encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const +{ + LLSD itemData; + + if (!isTerrain() && (pLinksetUse != kUnknown) && (getLinksetUse() != pLinksetUse) && + (canBeVolume() || ((pLinksetUse != kMaterialVolume) && (pLinksetUse != kExclusionVolume)))) + { + if (isModifiable()) + { + itemData[LINKSET_PHANTOM_FIELD] = static_cast(isPhantom(pLinksetUse)); + } + +#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + itemData[DEPRECATED_LINKSET_PERMANENT_FIELD] = static_cast(isPermanent(pLinksetUse)); + itemData[DEPRECATED_LINKSET_WALKABLE_FIELD] = static_cast(isWalkable(pLinksetUse)); +#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + itemData[LINKSET_CATEGORY_FIELD] = convertCategoryToLLSD(getNavMeshGenerationCategory(pLinksetUse)); + } + + if (mWalkabilityCoefficientA != pA) + { + itemData[LINKSET_WALKABILITY_A_FIELD] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + if (mWalkabilityCoefficientB != pB) + { + itemData[LINKSET_WALKABILITY_B_FIELD] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + if (mWalkabilityCoefficientC != pC) + { + itemData[LINKSET_WALKABILITY_C_FIELD] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + if (mWalkabilityCoefficientD != pD) + { + itemData[LINKSET_WALKABILITY_D_FIELD] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + return itemData; +} + +void LLPathfindingLinkset::parseObjectData(const LLSD &pLinksetItem) +{ + llassert(pLinksetItem.has(LINKSET_NAME_FIELD)); + llassert(pLinksetItem.get(LINKSET_NAME_FIELD).isString()); + mName = pLinksetItem.get(LINKSET_NAME_FIELD).asString(); + + llassert(pLinksetItem.has(LINKSET_DESCRIPTION_FIELD)); + llassert(pLinksetItem.get(LINKSET_DESCRIPTION_FIELD).isString()); + mDescription = pLinksetItem.get(LINKSET_DESCRIPTION_FIELD).asString(); + + llassert(pLinksetItem.has(LINKSET_LAND_IMPACT_FIELD)); + llassert(pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).isInteger()); + llassert(pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).asInteger() >= 0); + mLandImpact = pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).asInteger(); + +#ifdef MISSING_MODIFIABLE_FIELD_WAR + mHasModifiable = pLinksetItem.has(LINKSET_MODIFIABLE_FIELD); + if (mHasModifiable) + { + llassert(pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); + mIsModifiable = pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); + } +#else // MISSING_MODIFIABLE_FIELD_WAR + llassert(pLinksetItem.has(LINKSET_MODIFIABLE_FIELD)); + llassert(pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); + mIsModifiable = pLinksetItem.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); +#endif // MISSING_MODIFIABLE_FIELD_WAR + + llassert(pLinksetItem.has(LINKSET_POSITION_FIELD)); + llassert(pLinksetItem.get(LINKSET_POSITION_FIELD).isArray()); + mLocation.setValue(pLinksetItem.get(LINKSET_POSITION_FIELD)); +} + +void LLPathfindingLinkset::parsePathfindingData(const LLSD &pLinksetItem) +{ + bool isPhantom = false; + if (pLinksetItem.has(LINKSET_PHANTOM_FIELD)) + { + llassert(pLinksetItem.get(LINKSET_PHANTOM_FIELD).isBoolean()); + isPhantom = pLinksetItem.get(LINKSET_PHANTOM_FIELD).asBoolean(); + } + +#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + if (pLinksetItem.has(LINKSET_CATEGORY_FIELD)) + { + mLinksetUse = getLinksetUse(isPhantom, convertCategoryFromLLSD(pLinksetItem.get(LINKSET_CATEGORY_FIELD))); + } + else + { + llassert(pLinksetItem.has(DEPRECATED_LINKSET_PERMANENT_FIELD)); + llassert(pLinksetItem.get(DEPRECATED_LINKSET_PERMANENT_FIELD).isBoolean()); + bool isPermanent = pLinksetItem.get(DEPRECATED_LINKSET_PERMANENT_FIELD).asBoolean(); + + llassert(pLinksetItem.has(DEPRECATED_LINKSET_WALKABLE_FIELD)); + llassert(pLinksetItem.get(DEPRECATED_LINKSET_WALKABLE_FIELD).isBoolean()); + bool isWalkable = pLinksetItem.get(DEPRECATED_LINKSET_WALKABLE_FIELD).asBoolean(); + + mLinksetUse = getLinksetUse(isPhantom, isPermanent, isWalkable); + } +#else // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + llassert(pLinksetItem.has(LINKSET_CATEGORY_FIELD)); + mLinksetUse = getLinksetUse(isPhantom, convertCategoryFromLLSD(pLinksetItem.get(LINKSET_CATEGORY_FIELD))); +#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + + if (pLinksetItem.has(LINKSET_CAN_BE_VOLUME)) + { + llassert(pLinksetItem.get(LINKSET_CAN_BE_VOLUME).isBoolean()); + mCanBeVolume = pLinksetItem.get(LINKSET_CAN_BE_VOLUME).asBoolean(); + } + + llassert(pLinksetItem.has(LINKSET_WALKABILITY_A_FIELD)); + llassert(pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).isInteger()); + mWalkabilityCoefficientA = pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).asInteger(); + llassert(mWalkabilityCoefficientA >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientA <= MAX_WALKABILITY_VALUE); + + llassert(pLinksetItem.has(LINKSET_WALKABILITY_B_FIELD)); + llassert(pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).isInteger()); + mWalkabilityCoefficientB = pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).asInteger(); + llassert(mWalkabilityCoefficientB >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientB <= MAX_WALKABILITY_VALUE); + + llassert(pLinksetItem.has(LINKSET_WALKABILITY_C_FIELD)); + llassert(pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).isInteger()); + mWalkabilityCoefficientC = pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).asInteger(); + llassert(mWalkabilityCoefficientC >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientC <= MAX_WALKABILITY_VALUE); + + llassert(pLinksetItem.has(LINKSET_WALKABILITY_D_FIELD)); + llassert(pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).isInteger()); + mWalkabilityCoefficientD = pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).asInteger(); + llassert(mWalkabilityCoefficientD >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientD <= MAX_WALKABILITY_VALUE); +} + +#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS +LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUse(bool pIsPhantom, bool pIsPermanent, bool pIsWalkable) +{ + return (pIsPhantom ? (pIsPermanent ? (pIsWalkable ? kMaterialVolume : kExclusionVolume) : kDynamicPhantom) : + (pIsPermanent ? (pIsWalkable ? kWalkable : kStaticObstacle) : kDynamicObstacle)); +} + +BOOL LLPathfindingLinkset::isPermanent(ELinksetUse pLinksetUse) +{ + BOOL retVal; + + switch (pLinksetUse) + { + case kWalkable : + case kStaticObstacle : + case kMaterialVolume : + case kExclusionVolume : + retVal = true; + break; + case kDynamicObstacle : + case kDynamicPhantom : + retVal = false; + break; + case kUnknown : + default : + retVal = false; + llassert(0); + break; + } + + return retVal; +} + +BOOL LLPathfindingLinkset::isWalkable(ELinksetUse pLinksetUse) +{ + BOOL retVal; + + switch (pLinksetUse) + { + case kWalkable : + case kMaterialVolume : + retVal = true; + break; + case kStaticObstacle : + case kDynamicObstacle : + case kExclusionVolume : + case kDynamicPhantom : + retVal = false; + break; + case kUnknown : + default : + retVal = false; + llassert(0); + break; + } + + return retVal; +} +#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + +BOOL LLPathfindingLinkset::isPhantom(ELinksetUse pLinksetUse) +{ + BOOL retVal; + + switch (pLinksetUse) + { + case kWalkable : + case kStaticObstacle : + case kDynamicObstacle : + retVal = false; + break; + case kMaterialVolume : + case kExclusionVolume : + case kDynamicPhantom : + retVal = true; + break; + case kUnknown : + default : + retVal = false; + llassert(0); + break; + } + + return retVal; +} + +LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUse(bool pIsPhantom, ENavMeshGenerationCategory pNavMeshGenerationCategory) +{ + ELinksetUse linksetUse = kUnknown; + + if (pIsPhantom) + { + switch (pNavMeshGenerationCategory) + { + case kNavMeshGenerationIgnore : + linksetUse = kDynamicPhantom; + break; + case kNavMeshGenerationInclude : + linksetUse = kMaterialVolume; + break; + case kNavMeshGenerationExclude : + linksetUse = kExclusionVolume; + break; + default : + linksetUse = kUnknown; + llassert(0); + break; + } + } + else + { + switch (pNavMeshGenerationCategory) + { + case kNavMeshGenerationIgnore : + linksetUse = kDynamicObstacle; + break; + case kNavMeshGenerationInclude : + linksetUse = kWalkable; + break; + case kNavMeshGenerationExclude : + linksetUse = kStaticObstacle; + break; + default : + linksetUse = kUnknown; + llassert(0); + break; + } + } + + return linksetUse; +} + +LLPathfindingLinkset::ENavMeshGenerationCategory LLPathfindingLinkset::getNavMeshGenerationCategory(ELinksetUse pLinksetUse) +{ + ENavMeshGenerationCategory navMeshGenerationCategory; + switch (pLinksetUse) + { + case kWalkable : + case kMaterialVolume : + navMeshGenerationCategory = kNavMeshGenerationInclude; + break; + case kStaticObstacle : + case kExclusionVolume : + navMeshGenerationCategory = kNavMeshGenerationExclude; + break; + case kDynamicObstacle : + case kDynamicPhantom : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + break; + case kUnknown : + default : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + llassert(0); + break; + } + + return navMeshGenerationCategory; +} + +LLSD LLPathfindingLinkset::convertCategoryToLLSD(ENavMeshGenerationCategory pNavMeshGenerationCategory) +{ + LLSD llsd; + + switch (pNavMeshGenerationCategory) + { + case kNavMeshGenerationIgnore : + llsd = static_cast(LINKSET_CATEGORY_VALUE_IGNORE); + break; + case kNavMeshGenerationInclude : + llsd = static_cast(LINKSET_CATEGORY_VALUE_INCLUDE); + break; + case kNavMeshGenerationExclude : + llsd = static_cast(LINKSET_CATEGORY_VALUE_EXCLUDE); + break; + default : + llsd = static_cast(LINKSET_CATEGORY_VALUE_IGNORE); + llassert(0); + break; + } + + return llsd; +} + +LLPathfindingLinkset::ENavMeshGenerationCategory LLPathfindingLinkset::convertCategoryFromLLSD(const LLSD &llsd) +{ + ENavMeshGenerationCategory navMeshGenerationCategory; + + llassert(llsd.isInteger()); + switch (llsd.asInteger()) + { + case LINKSET_CATEGORY_VALUE_IGNORE : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + break; + case LINKSET_CATEGORY_VALUE_INCLUDE : + navMeshGenerationCategory = kNavMeshGenerationInclude; + break; + case LINKSET_CATEGORY_VALUE_EXCLUDE : + navMeshGenerationCategory = kNavMeshGenerationExclude; + break; + default : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + llassert(0); + break; + } + + return navMeshGenerationCategory; +} diff --git a/indra/newview/llpathfindinglinkset.h b/indra/newview/llpathfindinglinkset.h index d8c1c9d795..6dfac31931 100644 --- a/indra/newview/llpathfindinglinkset.h +++ b/indra/newview/llpathfindinglinkset.h @@ -1,132 +1,132 @@ -/** - * @file llpathfindinglinkset.h - * @author William Todd Stinson - * @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPATHFINDINGLINKSET_H -#define LL_LLPATHFINDINGLINKSET_H - -#include "v3math.h" -#include "lluuid.h" - -#include - -class LLSD; -class LLPathfindingLinkset; - -typedef boost::shared_ptr LLPathfindingLinksetPtr; - -#define DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS -#define MISSING_MODIFIABLE_FIELD_WAR - -class LLPathfindingLinkset -{ -public: - typedef enum - { - kUnknown, - kWalkable, - kStaticObstacle, - kDynamicObstacle, - kMaterialVolume, - kExclusionVolume, - kDynamicPhantom - } ELinksetUse; - - LLPathfindingLinkset(const LLSD &pTerrainLinksetItem); - LLPathfindingLinkset(const std::string &pUUID, const LLSD &pLinksetItem); - LLPathfindingLinkset(const LLPathfindingLinkset& pOther); - virtual ~LLPathfindingLinkset(); - - LLPathfindingLinkset& operator = (const LLPathfindingLinkset& pOther); - - inline bool isTerrain() const {return mIsTerrain;}; - inline const LLUUID& getUUID() const {return mUUID;}; - inline const std::string& getName() const {return mName;}; - inline const std::string& getDescription() const {return mDescription;}; - inline U32 getLandImpact() const {return mLandImpact;}; - inline const LLVector3& getLocation() const {return mLocation;}; - BOOL isModifiable() const {return mIsModifiable;}; - BOOL isPhantom() const; - BOOL canBeVolume() const {return mCanBeVolume;}; - static ELinksetUse getLinksetUseWithToggledPhantom(ELinksetUse pLinksetUse); - - inline ELinksetUse getLinksetUse() const {return mLinksetUse;}; - - inline S32 getWalkabilityCoefficientA() const {return mWalkabilityCoefficientA;}; - inline S32 getWalkabilityCoefficientB() const {return mWalkabilityCoefficientB;}; - inline S32 getWalkabilityCoefficientC() const {return mWalkabilityCoefficientC;}; - inline S32 getWalkabilityCoefficientD() const {return mWalkabilityCoefficientD;}; - - bool isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const; - bool isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const; - LLSD encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; - - static const S32 MIN_WALKABILITY_VALUE; - static const S32 MAX_WALKABILITY_VALUE; - -protected: - -private: - typedef enum - { - kNavMeshGenerationIgnore, - kNavMeshGenerationInclude, - kNavMeshGenerationExclude - } ENavMeshGenerationCategory; - - void parseObjectData(const LLSD &pLinksetItem); - void parsePathfindingData(const LLSD &pLinksetItem); - -#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - static ELinksetUse getLinksetUse(bool pIsPhantom, bool pIsPermanent, bool pIsWalkable); - static BOOL isPermanent(ELinksetUse pLinksetUse); - static BOOL isWalkable(ELinksetUse pLinksetUse); -#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS - static BOOL isPhantom(ELinksetUse pLinksetUse); - static ELinksetUse getLinksetUse(bool pIsPhantom, ENavMeshGenerationCategory pNavMeshGenerationCategory); - static ENavMeshGenerationCategory getNavMeshGenerationCategory(ELinksetUse pLinksetUse); - static LLSD convertCategoryToLLSD(ENavMeshGenerationCategory pNavMeshGenerationCategory); - static ENavMeshGenerationCategory convertCategoryFromLLSD(const LLSD &llsd); - - LLUUID mUUID; - bool mIsTerrain; - std::string mName; - std::string mDescription; - U32 mLandImpact; - LLVector3 mLocation; -#ifdef MISSING_MODIFIABLE_FIELD_WAR - bool mHasModifiable; -#endif // MISSING_MODIFIABLE_FIELD_WAR - BOOL mIsModifiable; - BOOL mCanBeVolume; - ELinksetUse mLinksetUse; - S32 mWalkabilityCoefficientA; - S32 mWalkabilityCoefficientB; - S32 mWalkabilityCoefficientC; - S32 mWalkabilityCoefficientD; -}; - -#endif // LL_LLPATHFINDINGLINKSET_H +/** + * @file llpathfindinglinkset.h + * @author William Todd Stinson + * @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPATHFINDINGLINKSET_H +#define LL_LLPATHFINDINGLINKSET_H + +#include "v3math.h" +#include "lluuid.h" + +#include + +class LLSD; +class LLPathfindingLinkset; + +typedef boost::shared_ptr LLPathfindingLinksetPtr; + +#define DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS +#define MISSING_MODIFIABLE_FIELD_WAR + +class LLPathfindingLinkset +{ +public: + typedef enum + { + kUnknown, + kWalkable, + kStaticObstacle, + kDynamicObstacle, + kMaterialVolume, + kExclusionVolume, + kDynamicPhantom + } ELinksetUse; + + LLPathfindingLinkset(const LLSD &pTerrainLinksetItem); + LLPathfindingLinkset(const std::string &pUUID, const LLSD &pLinksetItem); + LLPathfindingLinkset(const LLPathfindingLinkset& pOther); + virtual ~LLPathfindingLinkset(); + + LLPathfindingLinkset& operator = (const LLPathfindingLinkset& pOther); + + inline bool isTerrain() const {return mIsTerrain;}; + inline const LLUUID& getUUID() const {return mUUID;}; + inline const std::string& getName() const {return mName;}; + inline const std::string& getDescription() const {return mDescription;}; + inline U32 getLandImpact() const {return mLandImpact;}; + inline const LLVector3& getLocation() const {return mLocation;}; + BOOL isModifiable() const {return mIsModifiable;}; + BOOL isPhantom() const; + BOOL canBeVolume() const {return mCanBeVolume;}; + static ELinksetUse getLinksetUseWithToggledPhantom(ELinksetUse pLinksetUse); + + inline ELinksetUse getLinksetUse() const {return mLinksetUse;}; + + inline S32 getWalkabilityCoefficientA() const {return mWalkabilityCoefficientA;}; + inline S32 getWalkabilityCoefficientB() const {return mWalkabilityCoefficientB;}; + inline S32 getWalkabilityCoefficientC() const {return mWalkabilityCoefficientC;}; + inline S32 getWalkabilityCoefficientD() const {return mWalkabilityCoefficientD;}; + + bool isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const; + bool isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const; + LLSD encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; + + static const S32 MIN_WALKABILITY_VALUE; + static const S32 MAX_WALKABILITY_VALUE; + +protected: + +private: + typedef enum + { + kNavMeshGenerationIgnore, + kNavMeshGenerationInclude, + kNavMeshGenerationExclude + } ENavMeshGenerationCategory; + + void parseObjectData(const LLSD &pLinksetItem); + void parsePathfindingData(const LLSD &pLinksetItem); + +#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + static ELinksetUse getLinksetUse(bool pIsPhantom, bool pIsPermanent, bool pIsWalkable); + static BOOL isPermanent(ELinksetUse pLinksetUse); + static BOOL isWalkable(ELinksetUse pLinksetUse); +#endif // DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + static BOOL isPhantom(ELinksetUse pLinksetUse); + static ELinksetUse getLinksetUse(bool pIsPhantom, ENavMeshGenerationCategory pNavMeshGenerationCategory); + static ENavMeshGenerationCategory getNavMeshGenerationCategory(ELinksetUse pLinksetUse); + static LLSD convertCategoryToLLSD(ENavMeshGenerationCategory pNavMeshGenerationCategory); + static ENavMeshGenerationCategory convertCategoryFromLLSD(const LLSD &llsd); + + LLUUID mUUID; + bool mIsTerrain; + std::string mName; + std::string mDescription; + U32 mLandImpact; + LLVector3 mLocation; +#ifdef MISSING_MODIFIABLE_FIELD_WAR + bool mHasModifiable; +#endif // MISSING_MODIFIABLE_FIELD_WAR + BOOL mIsModifiable; + BOOL mCanBeVolume; + ELinksetUse mLinksetUse; + S32 mWalkabilityCoefficientA; + S32 mWalkabilityCoefficientB; + S32 mWalkabilityCoefficientC; + S32 mWalkabilityCoefficientD; +}; + +#endif // LL_LLPATHFINDINGLINKSET_H diff --git a/indra/newview/llpathfindinglinksetlist.cpp b/indra/newview/llpathfindinglinksetlist.cpp index 57febbf0f2..19a99ef444 100644 --- a/indra/newview/llpathfindinglinksetlist.cpp +++ b/indra/newview/llpathfindinglinksetlist.cpp @@ -1,122 +1,122 @@ -/** - * @file llpathfindinglinksetlist.cpp - * @author William Todd Stinson - * @brief Class to implement the list of a set of pathfinding linksets - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include -#include - -#include "llsd.h" -#include "lluuid.h" -#include "llpathfindinglinkset.h" -#include "llpathfindinglinksetlist.h" - -//--------------------------------------------------------------------------- -// LLPathfindingLinksetList -//--------------------------------------------------------------------------- - -LLPathfindingLinksetList::LLPathfindingLinksetList() - : LLPathfindingLinksetMap() -{ -} - -LLPathfindingLinksetList::LLPathfindingLinksetList(const LLSD& pLinksetItems) - : LLPathfindingLinksetMap() -{ - for (LLSD::map_const_iterator linksetItemIter = pLinksetItems.beginMap(); - linksetItemIter != pLinksetItems.endMap(); ++linksetItemIter) - { - const std::string& uuid(linksetItemIter->first); - const LLSD& linksetData = linksetItemIter->second; - LLPathfindingLinksetPtr linkset(new LLPathfindingLinkset(uuid, linksetData)); - insert(std::pair(uuid, linkset)); - } -} - -LLPathfindingLinksetList::~LLPathfindingLinksetList() -{ - clear(); -} - -void LLPathfindingLinksetList::update(const LLPathfindingLinksetList &pUpdateLinksetList) -{ - for (LLPathfindingLinksetList::const_iterator updateLinksetIter = pUpdateLinksetList.begin(); - updateLinksetIter != pUpdateLinksetList.end(); ++updateLinksetIter) - { - const std::string &uuid = updateLinksetIter->first; - const LLPathfindingLinksetPtr updateLinksetPtr = updateLinksetIter->second; - - LLPathfindingLinksetList::iterator linksetIter = find(uuid); - if (linksetIter == end()) - { - insert(std::pair(uuid, updateLinksetPtr)); - } - else - { - LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - *linksetPtr = *updateLinksetPtr; - } - } -} - -LLSD LLPathfindingLinksetList::encodeObjectFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const -{ - LLSD listData; - - for (LLPathfindingLinksetMap::const_iterator linksetIter = begin(); linksetIter != end(); ++linksetIter) - { - const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - if (!linksetPtr->isTerrain()) - { - LLSD linksetData = linksetPtr->encodeAlteredFields(pLinksetUse, pA, pB, pC, pD); - if (!linksetData.isUndefined()) - { - const std::string& uuid(linksetIter->first); - listData[uuid] = linksetData; - } - } - } - - return listData; -} - -LLSD LLPathfindingLinksetList::encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const -{ - LLSD terrainData; - - for (LLPathfindingLinksetMap::const_iterator linksetIter = begin(); linksetIter != end(); ++linksetIter) - { - const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; - if (linksetPtr->isTerrain()) - { - terrainData = linksetPtr->encodeAlteredFields(pLinksetUse, pA, pB, pC, pD); - break; - } - } - - return terrainData; -} +/** + * @file llpathfindinglinksetlist.cpp + * @author William Todd Stinson + * @brief Class to implement the list of a set of pathfinding linksets + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include +#include + +#include "llsd.h" +#include "lluuid.h" +#include "llpathfindinglinkset.h" +#include "llpathfindinglinksetlist.h" + +//--------------------------------------------------------------------------- +// LLPathfindingLinksetList +//--------------------------------------------------------------------------- + +LLPathfindingLinksetList::LLPathfindingLinksetList() + : LLPathfindingLinksetMap() +{ +} + +LLPathfindingLinksetList::LLPathfindingLinksetList(const LLSD& pLinksetItems) + : LLPathfindingLinksetMap() +{ + for (LLSD::map_const_iterator linksetItemIter = pLinksetItems.beginMap(); + linksetItemIter != pLinksetItems.endMap(); ++linksetItemIter) + { + const std::string& uuid(linksetItemIter->first); + const LLSD& linksetData = linksetItemIter->second; + LLPathfindingLinksetPtr linkset(new LLPathfindingLinkset(uuid, linksetData)); + insert(std::pair(uuid, linkset)); + } +} + +LLPathfindingLinksetList::~LLPathfindingLinksetList() +{ + clear(); +} + +void LLPathfindingLinksetList::update(const LLPathfindingLinksetList &pUpdateLinksetList) +{ + for (LLPathfindingLinksetList::const_iterator updateLinksetIter = pUpdateLinksetList.begin(); + updateLinksetIter != pUpdateLinksetList.end(); ++updateLinksetIter) + { + const std::string &uuid = updateLinksetIter->first; + const LLPathfindingLinksetPtr updateLinksetPtr = updateLinksetIter->second; + + LLPathfindingLinksetList::iterator linksetIter = find(uuid); + if (linksetIter == end()) + { + insert(std::pair(uuid, updateLinksetPtr)); + } + else + { + LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + *linksetPtr = *updateLinksetPtr; + } + } +} + +LLSD LLPathfindingLinksetList::encodeObjectFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const +{ + LLSD listData; + + for (LLPathfindingLinksetMap::const_iterator linksetIter = begin(); linksetIter != end(); ++linksetIter) + { + const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + if (!linksetPtr->isTerrain()) + { + LLSD linksetData = linksetPtr->encodeAlteredFields(pLinksetUse, pA, pB, pC, pD); + if (!linksetData.isUndefined()) + { + const std::string& uuid(linksetIter->first); + listData[uuid] = linksetData; + } + } + } + + return listData; +} + +LLSD LLPathfindingLinksetList::encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const +{ + LLSD terrainData; + + for (LLPathfindingLinksetMap::const_iterator linksetIter = begin(); linksetIter != end(); ++linksetIter) + { + const LLPathfindingLinksetPtr linksetPtr = linksetIter->second; + if (linksetPtr->isTerrain()) + { + terrainData = linksetPtr->encodeAlteredFields(pLinksetUse, pA, pB, pC, pD); + break; + } + } + + return terrainData; +} diff --git a/indra/newview/llpathfindinglinksetlist.h b/indra/newview/llpathfindinglinksetlist.h index 813c4ec46c..855b1cc451 100644 --- a/indra/newview/llpathfindinglinksetlist.h +++ b/indra/newview/llpathfindinglinksetlist.h @@ -1,61 +1,61 @@ -/** - * @file llpathfindinglinksetlist.h - * @author William Todd Stinson - * @brief Class to implement the list of a set of pathfinding linksets - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPATHFINDINGLINKSETLIST_H -#define LL_LLPATHFINDINGLINKSETLIST_H - -#include -#include -#include "llpathfindinglinkset.h" - -#include - -class LLSD; -class LLPathfindingLinksetList; - -typedef boost::shared_ptr LLPathfindingLinksetListPtr; -typedef std::map LLPathfindingLinksetMap; - -class LLPathfindingLinksetList : public LLPathfindingLinksetMap -{ -public: - LLPathfindingLinksetList(); - LLPathfindingLinksetList(const LLSD& pLinksetItems); - virtual ~LLPathfindingLinksetList(); - - void update(const LLPathfindingLinksetList &pUpdateLinksetList); - - LLSD encodeObjectFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; - LLSD encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; - -protected: - -private: - -}; - -#endif // LL_LLPATHFINDINGLINKSETLIST_H +/** + * @file llpathfindinglinksetlist.h + * @author William Todd Stinson + * @brief Class to implement the list of a set of pathfinding linksets + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPATHFINDINGLINKSETLIST_H +#define LL_LLPATHFINDINGLINKSETLIST_H + +#include +#include +#include "llpathfindinglinkset.h" + +#include + +class LLSD; +class LLPathfindingLinksetList; + +typedef boost::shared_ptr LLPathfindingLinksetListPtr; +typedef std::map LLPathfindingLinksetMap; + +class LLPathfindingLinksetList : public LLPathfindingLinksetMap +{ +public: + LLPathfindingLinksetList(); + LLPathfindingLinksetList(const LLSD& pLinksetItems); + virtual ~LLPathfindingLinksetList(); + + void update(const LLPathfindingLinksetList &pUpdateLinksetList); + + LLSD encodeObjectFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; + LLSD encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; + +protected: + +private: + +}; + +#endif // LL_LLPATHFINDINGLINKSETLIST_H diff --git a/indra/newview/llpathfindingnavmeshstatus.cpp b/indra/newview/llpathfindingnavmeshstatus.cpp index 0ba28e0297..31ff85c1a1 100644 --- a/indra/newview/llpathfindingnavmeshstatus.cpp +++ b/indra/newview/llpathfindingnavmeshstatus.cpp @@ -1,159 +1,159 @@ -/** - * @file llpathfindingnavmeshstatus.cpp - * @author William Todd Stinson - * @brief A class for representing the navmesh status of a pathfinding region. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llsd.h" -#include "lluuid.h" -#include "llstring.h" -#include "llpathfindingnavmeshstatus.h" - -#include - -#define REGION_FIELD "region_id" -#define DEPRECATED_STATE_FIELD "state" -#define STATUS_FIELD "status" -#define VERSION_FIELD "version" - -const std::string LLPathfindingNavMeshStatus::sStatusPending("pending"); -const std::string LLPathfindingNavMeshStatus::sStatusBuilding("building"); -const std::string LLPathfindingNavMeshStatus::sStatusComplete("complete"); -const std::string LLPathfindingNavMeshStatus::sStatusRepending("repending"); - - -//--------------------------------------------------------------------------- -// LLPathfindingNavMeshStatus -//--------------------------------------------------------------------------- - -LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus() - : mIsValid(false), - mRegionUUID(), - mVersion(0U), - mStatus(kComplete) -{ -} - -LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID) - : mIsValid(false), - mRegionUUID(pRegionUUID), - mVersion(0U), - mStatus(kComplete) -{ -} - -LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID, const LLSD &pContent) - : mIsValid(true), - mRegionUUID(pRegionUUID), - mVersion(0U), - mStatus(kComplete) -{ - parseStatus(pContent); -} - -LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLSD &pContent) - : mIsValid(true), - mRegionUUID(), - mVersion(0U), - mStatus(kComplete) -{ - llassert(pContent.has(REGION_FIELD)); - llassert(pContent.get(REGION_FIELD).isUUID()); - mRegionUUID = pContent.get(REGION_FIELD).asUUID(); - - parseStatus(pContent); -} - -LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLPathfindingNavMeshStatus &pOther) - : mIsValid(pOther.mIsValid), - mRegionUUID(pOther.mRegionUUID), - mVersion(pOther.mVersion), - mStatus(pOther.mStatus) -{ -} - -LLPathfindingNavMeshStatus::~LLPathfindingNavMeshStatus() -{ -} - -LLPathfindingNavMeshStatus &LLPathfindingNavMeshStatus::operator =(const LLPathfindingNavMeshStatus &pOther) -{ - mIsValid = pOther.mIsValid; - mRegionUUID = pOther.mRegionUUID; - mVersion = pOther.mVersion; - mStatus = pOther.mStatus; - - return *this; -} - -void LLPathfindingNavMeshStatus::parseStatus(const LLSD &pContent) -{ - llassert(pContent.has(VERSION_FIELD)); - llassert(pContent.get(VERSION_FIELD).isInteger()); - llassert(pContent.get(VERSION_FIELD).asInteger() >= 0); - mVersion = static_cast(pContent.get(VERSION_FIELD).asInteger()); - -#ifdef DEPRECATED_STATE_FIELD - std::string status; - if (pContent.has(DEPRECATED_STATE_FIELD)) - { - llassert(pContent.has(DEPRECATED_STATE_FIELD)); - llassert(pContent.get(DEPRECATED_STATE_FIELD).isString()); - status = pContent.get(DEPRECATED_STATE_FIELD).asString(); - } - else - { - llassert(pContent.has(STATUS_FIELD)); - llassert(pContent.get(STATUS_FIELD).isString()); - status = pContent.get(STATUS_FIELD).asString(); - } -#else // DEPRECATED_STATE_FIELD - llassert(pContent.has(STATUS_FIELD)); - llassert(pContent.get(STATUS_FIELD).isString()); - std::string status = pContent.get(STATUS_FIELD).asString(); -#endif // DEPRECATED_STATE_FIELD - - if (LLStringUtil::compareStrings(status, sStatusPending) == 0) - { - mStatus = kPending; - } - else if (LLStringUtil::compareStrings(status, sStatusBuilding) == 0) - { - mStatus = kBuilding; - } - else if (LLStringUtil::compareStrings(status, sStatusComplete) == 0) - { - mStatus = kComplete; - } - else if (LLStringUtil::compareStrings(status, sStatusRepending) == 0) - { - mStatus = kRepending; - } - else - { - mStatus = kComplete; - llassert(0); - } -} +/** + * @file llpathfindingnavmeshstatus.cpp + * @author William Todd Stinson + * @brief A class for representing the navmesh status of a pathfinding region. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llsd.h" +#include "lluuid.h" +#include "llstring.h" +#include "llpathfindingnavmeshstatus.h" + +#include + +#define REGION_FIELD "region_id" +#define DEPRECATED_STATE_FIELD "state" +#define STATUS_FIELD "status" +#define VERSION_FIELD "version" + +const std::string LLPathfindingNavMeshStatus::sStatusPending("pending"); +const std::string LLPathfindingNavMeshStatus::sStatusBuilding("building"); +const std::string LLPathfindingNavMeshStatus::sStatusComplete("complete"); +const std::string LLPathfindingNavMeshStatus::sStatusRepending("repending"); + + +//--------------------------------------------------------------------------- +// LLPathfindingNavMeshStatus +//--------------------------------------------------------------------------- + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus() + : mIsValid(false), + mRegionUUID(), + mVersion(0U), + mStatus(kComplete) +{ +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID) + : mIsValid(false), + mRegionUUID(pRegionUUID), + mVersion(0U), + mStatus(kComplete) +{ +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID, const LLSD &pContent) + : mIsValid(true), + mRegionUUID(pRegionUUID), + mVersion(0U), + mStatus(kComplete) +{ + parseStatus(pContent); +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLSD &pContent) + : mIsValid(true), + mRegionUUID(), + mVersion(0U), + mStatus(kComplete) +{ + llassert(pContent.has(REGION_FIELD)); + llassert(pContent.get(REGION_FIELD).isUUID()); + mRegionUUID = pContent.get(REGION_FIELD).asUUID(); + + parseStatus(pContent); +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLPathfindingNavMeshStatus &pOther) + : mIsValid(pOther.mIsValid), + mRegionUUID(pOther.mRegionUUID), + mVersion(pOther.mVersion), + mStatus(pOther.mStatus) +{ +} + +LLPathfindingNavMeshStatus::~LLPathfindingNavMeshStatus() +{ +} + +LLPathfindingNavMeshStatus &LLPathfindingNavMeshStatus::operator =(const LLPathfindingNavMeshStatus &pOther) +{ + mIsValid = pOther.mIsValid; + mRegionUUID = pOther.mRegionUUID; + mVersion = pOther.mVersion; + mStatus = pOther.mStatus; + + return *this; +} + +void LLPathfindingNavMeshStatus::parseStatus(const LLSD &pContent) +{ + llassert(pContent.has(VERSION_FIELD)); + llassert(pContent.get(VERSION_FIELD).isInteger()); + llassert(pContent.get(VERSION_FIELD).asInteger() >= 0); + mVersion = static_cast(pContent.get(VERSION_FIELD).asInteger()); + +#ifdef DEPRECATED_STATE_FIELD + std::string status; + if (pContent.has(DEPRECATED_STATE_FIELD)) + { + llassert(pContent.has(DEPRECATED_STATE_FIELD)); + llassert(pContent.get(DEPRECATED_STATE_FIELD).isString()); + status = pContent.get(DEPRECATED_STATE_FIELD).asString(); + } + else + { + llassert(pContent.has(STATUS_FIELD)); + llassert(pContent.get(STATUS_FIELD).isString()); + status = pContent.get(STATUS_FIELD).asString(); + } +#else // DEPRECATED_STATE_FIELD + llassert(pContent.has(STATUS_FIELD)); + llassert(pContent.get(STATUS_FIELD).isString()); + std::string status = pContent.get(STATUS_FIELD).asString(); +#endif // DEPRECATED_STATE_FIELD + + if (LLStringUtil::compareStrings(status, sStatusPending) == 0) + { + mStatus = kPending; + } + else if (LLStringUtil::compareStrings(status, sStatusBuilding) == 0) + { + mStatus = kBuilding; + } + else if (LLStringUtil::compareStrings(status, sStatusComplete) == 0) + { + mStatus = kComplete; + } + else if (LLStringUtil::compareStrings(status, sStatusRepending) == 0) + { + mStatus = kRepending; + } + else + { + mStatus = kComplete; + llassert(0); + } +} diff --git a/indra/newview/llpathfindingnavmeshstatus.h b/indra/newview/llpathfindingnavmeshstatus.h index 7147fcdf36..6428a31c24 100644 --- a/indra/newview/llpathfindingnavmeshstatus.h +++ b/indra/newview/llpathfindingnavmeshstatus.h @@ -1,85 +1,85 @@ -/** - * @file llpathfindingnavmeshstatus.h - * @author William Todd Stinson - * @brief A class for representing the navmesh status of a pathfinding region. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPATHFINDINGNAVMESHSTATUS_H -#define LL_LLPATHFINDINGNAVMESHSTATUS_H - -#include "lluuid.h" - -#include - -// XXX stinson 03/12/2012 : This definition is in place to support an older version of the pathfinding simulator that does not have versioned information -#define DEPRECATED_UNVERSIONED_NAVMESH - -class LLSD; - -class LLPathfindingNavMeshStatus -{ -public: - typedef enum - { - kPending, - kBuilding, - kComplete, - kRepending - } ENavMeshStatus; - - LLPathfindingNavMeshStatus(); - LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID); - LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID, const LLSD &pContent); - LLPathfindingNavMeshStatus(const LLSD &pContent); - LLPathfindingNavMeshStatus(const LLPathfindingNavMeshStatus &pOther); - virtual ~LLPathfindingNavMeshStatus(); - - LLPathfindingNavMeshStatus &operator =(const LLPathfindingNavMeshStatus &pOther); - -#ifdef DEPRECATED_UNVERSIONED_NAVMESH - void incrementNavMeshVersionXXX() {++mVersion;}; -#endif // DEPRECATED_UNVERSIONED_NAVMESH - - bool isValid() const {return mIsValid;}; - const LLUUID &getRegionUUID() const {return mRegionUUID;}; - U32 getVersion() const {return mVersion;}; - ENavMeshStatus getStatus() const {return mStatus;}; - -protected: - -private: - void parseStatus(const LLSD &pContent); - - bool mIsValid; - LLUUID mRegionUUID; - U32 mVersion; - ENavMeshStatus mStatus; - - static const std::string sStatusPending; - static const std::string sStatusBuilding; - static const std::string sStatusComplete; - static const std::string sStatusRepending; -}; - -#endif // LL_LLPATHFINDINGNAVMESHSTATUS_H +/** + * @file llpathfindingnavmeshstatus.h + * @author William Todd Stinson + * @brief A class for representing the navmesh status of a pathfinding region. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPATHFINDINGNAVMESHSTATUS_H +#define LL_LLPATHFINDINGNAVMESHSTATUS_H + +#include "lluuid.h" + +#include + +// XXX stinson 03/12/2012 : This definition is in place to support an older version of the pathfinding simulator that does not have versioned information +#define DEPRECATED_UNVERSIONED_NAVMESH + +class LLSD; + +class LLPathfindingNavMeshStatus +{ +public: + typedef enum + { + kPending, + kBuilding, + kComplete, + kRepending + } ENavMeshStatus; + + LLPathfindingNavMeshStatus(); + LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID); + LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID, const LLSD &pContent); + LLPathfindingNavMeshStatus(const LLSD &pContent); + LLPathfindingNavMeshStatus(const LLPathfindingNavMeshStatus &pOther); + virtual ~LLPathfindingNavMeshStatus(); + + LLPathfindingNavMeshStatus &operator =(const LLPathfindingNavMeshStatus &pOther); + +#ifdef DEPRECATED_UNVERSIONED_NAVMESH + void incrementNavMeshVersionXXX() {++mVersion;}; +#endif // DEPRECATED_UNVERSIONED_NAVMESH + + bool isValid() const {return mIsValid;}; + const LLUUID &getRegionUUID() const {return mRegionUUID;}; + U32 getVersion() const {return mVersion;}; + ENavMeshStatus getStatus() const {return mStatus;}; + +protected: + +private: + void parseStatus(const LLSD &pContent); + + bool mIsValid; + LLUUID mRegionUUID; + U32 mVersion; + ENavMeshStatus mStatus; + + static const std::string sStatusPending; + static const std::string sStatusBuilding; + static const std::string sStatusComplete; + static const std::string sStatusRepending; +}; + +#endif // LL_LLPATHFINDINGNAVMESHSTATUS_H diff --git a/indra/newview/llpathfindingpathtool.cpp b/indra/newview/llpathfindingpathtool.cpp index 04ea400090..8825f82f29 100644 --- a/indra/newview/llpathfindingpathtool.cpp +++ b/indra/newview/llpathfindingpathtool.cpp @@ -1,429 +1,429 @@ -/** - * @file llpathfindingpathtool.cpp - * @author William Todd Stinson - * @brief XXX - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llpathfindingpathtool.h" -#include "llsingleton.h" -#include "lltool.h" -#include "llviewerwindow.h" -#include "llviewercamera.h" -#include "llpathfindingmanager.h" -#include "llpathinglib.h" - -#include -#include - -#define PATH_TOOL_NAME "PathfindingPathTool" - -LLPathfindingPathTool::LLPathfindingPathTool() - : LLTool(PATH_TOOL_NAME), - LLSingleton(), - mFinalPathData(), - mTempPathData(), - mPathResult(LLPathingLib::LLPL_NO_PATH), - mCharacterType(kCharacterTypeNone), - mPathEventSignal(), - mIsLeftMouseButtonHeld(false), - mIsMiddleMouseButtonHeld(false), - mIsRightMouseButtonHeld(false) -{ - if (!LLPathingLib::getInstance()) - { - LLPathingLib::initSystem(); - } - - setCharacterWidth(1.0f); - setCharacterType(mCharacterType); -} - -LLPathfindingPathTool::~LLPathfindingPathTool() -{ -} - -BOOL LLPathfindingPathTool::handleMouseDown(S32 pX, S32 pY, MASK pMask) -{ - BOOL returnVal = FALSE; - - if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask)) - { - computeFinalPoints(pX, pY, pMask); - mIsLeftMouseButtonHeld = true; - setMouseCapture(TRUE); - returnVal = TRUE; - } - mIsLeftMouseButtonHeld = true; - - return returnVal; -} - -BOOL LLPathfindingPathTool::handleMouseUp(S32 pX, S32 pY, MASK pMask) -{ - BOOL returnVal = FALSE; - - if (mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask)) - { - computeFinalPoints(pX, pY, pMask); - setMouseCapture(FALSE); - returnVal = TRUE; - } - mIsLeftMouseButtonHeld = false; - - return returnVal; -} - -BOOL LLPathfindingPathTool::handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask) -{ - setMouseCapture(TRUE); - mIsMiddleMouseButtonHeld = true; - gViewerWindow->setCursor(UI_CURSOR_TOOLNO); - - return TRUE; -} - -BOOL LLPathfindingPathTool::handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask) -{ - if (!mIsLeftMouseButtonHeld && mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld) - { - setMouseCapture(FALSE); - } - mIsMiddleMouseButtonHeld = false; - - return TRUE; -} - -BOOL LLPathfindingPathTool::handleRightMouseDown(S32 pX, S32 pY, MASK pMask) -{ - setMouseCapture(TRUE); - mIsRightMouseButtonHeld = true; - gViewerWindow->setCursor(UI_CURSOR_TOOLNO); - - return TRUE; -} - -BOOL LLPathfindingPathTool::handleRightMouseUp(S32 pX, S32 pY, MASK pMask) -{ - if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && mIsRightMouseButtonHeld) - { - setMouseCapture(FALSE); - } - mIsRightMouseButtonHeld = false; - - return TRUE; -} - -BOOL LLPathfindingPathTool::handleDoubleClick(S32 pX, S32 pY, MASK pMask) -{ - return TRUE; -} - -BOOL LLPathfindingPathTool::handleHover(S32 pX, S32 pY, MASK pMask) -{ - BOOL returnVal = FALSE; - - if (!mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask)) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING); - computeTempPoints(pX, pY, pMask); - returnVal = TRUE; - } - else - { - clearTemp(); - computeFinalPath(); - } - - return returnVal; -} - -LLPathfindingPathTool::EPathStatus LLPathfindingPathTool::getPathStatus() const -{ - EPathStatus status = kPathStatusUnknown; - - if (LLPathingLib::getInstance() == NULL) - { - status = kPathStatusNotImplemented; - } - else if (!LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion()) - { - status = kPathStatusNotEnabled; - } - else if (!hasFinalA() && !hasFinalB()) - { - status = kPathStatusChooseStartAndEndPoints; - } - else if (!hasFinalA()) - { - status = kPathStatusChooseStartPoint; - } - else if (!hasFinalB()) - { - status = kPathStatusChooseEndPoint; - } - else if (mPathResult == LLPathingLib::LLPL_PATH_GENERATED_OK) - { - status = kPathStatusHasValidPath; - } - else if (mPathResult == LLPathingLib::LLPL_NO_PATH) - { - status = kPathStatusHasInvalidPath; - } - else - { - status = kPathStatusError; - } - - return status; -} - -F32 LLPathfindingPathTool::getCharacterWidth() const -{ - return mFinalPathData.mCharacterWidth; -} - -void LLPathfindingPathTool::setCharacterWidth(F32 pCharacterWidth) -{ - mFinalPathData.mCharacterWidth = pCharacterWidth; - mTempPathData.mCharacterWidth = pCharacterWidth; - computeFinalPath(); -} - -LLPathfindingPathTool::ECharacterType LLPathfindingPathTool::getCharacterType() const -{ - return mCharacterType; -} - -void LLPathfindingPathTool::setCharacterType(ECharacterType pCharacterType) -{ - mCharacterType = pCharacterType; - - LLPathingLib::LLPLCharacterType characterType; - switch (pCharacterType) - { - case kCharacterTypeNone : - characterType = LLPathingLib::LLPL_CHARACTER_TYPE_NONE; - break; - case kCharacterTypeA : - characterType = LLPathingLib::LLPL_CHARACTER_TYPE_A; - break; - case kCharacterTypeB : - characterType = LLPathingLib::LLPL_CHARACTER_TYPE_B; - break; - case kCharacterTypeC : - characterType = LLPathingLib::LLPL_CHARACTER_TYPE_C; - break; - case kCharacterTypeD : - characterType = LLPathingLib::LLPL_CHARACTER_TYPE_D; - break; - default : - characterType = LLPathingLib::LLPL_CHARACTER_TYPE_NONE; - llassert(0); - break; - } - mFinalPathData.mCharacterType = characterType; - mTempPathData.mCharacterType = characterType; - computeFinalPath(); -} - -bool LLPathfindingPathTool::isRenderPath() const -{ - return (hasFinalA() || hasFinalB() || hasTempA() || hasTempB()); -} - -void LLPathfindingPathTool::clearPath() -{ - clearFinal(); - clearTemp(); - computeFinalPath(); -} - -LLPathfindingPathTool::path_event_slot_t LLPathfindingPathTool::registerPathEventListener(path_event_callback_t pPathEventCallback) -{ - return mPathEventSignal.connect(pPathEventCallback); -} - -bool LLPathfindingPathTool::isAnyPathToolModKeys(MASK pMask) const -{ - return ((pMask & (MASK_CONTROL|MASK_SHIFT)) != 0); -} - -bool LLPathfindingPathTool::isPointAModKeys(MASK pMask) const -{ - return ((pMask & MASK_CONTROL) != 0); -} - -bool LLPathfindingPathTool::isPointBModKeys(MASK pMask) const -{ - return ((pMask & MASK_SHIFT) != 0); -} - -void LLPathfindingPathTool::getRayPoints(S32 pX, S32 pY, LLVector3 &pRayStart, LLVector3 &pRayEnd) const -{ - LLVector3 dv = gViewerWindow->mouseDirectionGlobal(pX, pY); - LLVector3 mousePos = LLViewerCamera::getInstance()->getOrigin(); - pRayStart = mousePos; - pRayEnd = mousePos + dv * 150; -} - -void LLPathfindingPathTool::computeFinalPoints(S32 pX, S32 pY, MASK pMask) -{ - LLVector3 rayStart, rayEnd; - getRayPoints(pX, pY, rayStart, rayEnd); - - if (isPointAModKeys(pMask)) - { - setFinalA(rayStart, rayEnd); - } - else if (isPointBModKeys(pMask)) - { - setFinalB(rayStart, rayEnd); - } - computeFinalPath(); -} - -void LLPathfindingPathTool::computeTempPoints(S32 pX, S32 pY, MASK pMask) -{ - LLVector3 rayStart, rayEnd; - getRayPoints(pX, pY, rayStart, rayEnd); - - if (isPointAModKeys(pMask)) - { - setTempA(rayStart, rayEnd); - if (hasFinalB()) - { - setTempB(getFinalBStart(), getFinalBEnd()); - } - } - else if (isPointBModKeys(pMask)) - { - if (hasFinalA()) - { - setTempA(getFinalAStart(), getFinalAEnd()); - } - setTempB(rayStart, rayEnd); - } - computeTempPath(); -} - -void LLPathfindingPathTool::setFinalA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) -{ - mFinalPathData.mStartPointA = pStartPoint; - mFinalPathData.mEndPointA = pEndPoint; - mFinalPathData.mHasPointA = true; -} - -bool LLPathfindingPathTool::hasFinalA() const -{ - return mFinalPathData.mHasPointA; -} - -const LLVector3 &LLPathfindingPathTool::getFinalAStart() const -{ - return mFinalPathData.mStartPointA; -} - -const LLVector3 &LLPathfindingPathTool::getFinalAEnd() const -{ - return mFinalPathData.mEndPointA; -} - -void LLPathfindingPathTool::setTempA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) -{ - mTempPathData.mStartPointA = pStartPoint; - mTempPathData.mEndPointA = pEndPoint; - mTempPathData.mHasPointA = true; -} - -bool LLPathfindingPathTool::hasTempA() const -{ - return mTempPathData.mHasPointA; -} - -void LLPathfindingPathTool::setFinalB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) -{ - mFinalPathData.mStartPointB = pStartPoint; - mFinalPathData.mEndPointB = pEndPoint; - mFinalPathData.mHasPointB = true; -} - -bool LLPathfindingPathTool::hasFinalB() const -{ - return mFinalPathData.mHasPointB; -} - -const LLVector3 &LLPathfindingPathTool::getFinalBStart() const -{ - return mFinalPathData.mStartPointB; -} - -const LLVector3 &LLPathfindingPathTool::getFinalBEnd() const -{ - return mFinalPathData.mEndPointB; -} - -void LLPathfindingPathTool::setTempB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) -{ - mTempPathData.mStartPointB = pStartPoint; - mTempPathData.mEndPointB = pEndPoint; - mTempPathData.mHasPointB = true; -} - -bool LLPathfindingPathTool::hasTempB() const -{ - return mTempPathData.mHasPointB; -} - -void LLPathfindingPathTool::clearFinal() -{ - mFinalPathData.mHasPointA = false; - mFinalPathData.mHasPointB = false; -} - -void LLPathfindingPathTool::clearTemp() -{ - mTempPathData.mHasPointA = false; - mTempPathData.mHasPointB = false; -} - -void LLPathfindingPathTool::computeFinalPath() -{ - mPathResult = LLPathingLib::LLPL_NO_PATH; - if (LLPathingLib::getInstance() != NULL) - { - mPathResult = LLPathingLib::getInstance()->generatePath(mFinalPathData); - } - mPathEventSignal(); -} - -void LLPathfindingPathTool::computeTempPath() -{ - mPathResult = LLPathingLib::LLPL_NO_PATH; - if (LLPathingLib::getInstance() != NULL) - { - mPathResult = LLPathingLib::getInstance()->generatePath(mTempPathData); - } - mPathEventSignal(); -} +/** + * @file llpathfindingpathtool.cpp + * @author William Todd Stinson + * @brief XXX + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llpathfindingpathtool.h" +#include "llsingleton.h" +#include "lltool.h" +#include "llviewerwindow.h" +#include "llviewercamera.h" +#include "llpathfindingmanager.h" +#include "llpathinglib.h" + +#include +#include + +#define PATH_TOOL_NAME "PathfindingPathTool" + +LLPathfindingPathTool::LLPathfindingPathTool() + : LLTool(PATH_TOOL_NAME), + LLSingleton(), + mFinalPathData(), + mTempPathData(), + mPathResult(LLPathingLib::LLPL_NO_PATH), + mCharacterType(kCharacterTypeNone), + mPathEventSignal(), + mIsLeftMouseButtonHeld(false), + mIsMiddleMouseButtonHeld(false), + mIsRightMouseButtonHeld(false) +{ + if (!LLPathingLib::getInstance()) + { + LLPathingLib::initSystem(); + } + + setCharacterWidth(1.0f); + setCharacterType(mCharacterType); +} + +LLPathfindingPathTool::~LLPathfindingPathTool() +{ +} + +BOOL LLPathfindingPathTool::handleMouseDown(S32 pX, S32 pY, MASK pMask) +{ + BOOL returnVal = FALSE; + + if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask)) + { + computeFinalPoints(pX, pY, pMask); + mIsLeftMouseButtonHeld = true; + setMouseCapture(TRUE); + returnVal = TRUE; + } + mIsLeftMouseButtonHeld = true; + + return returnVal; +} + +BOOL LLPathfindingPathTool::handleMouseUp(S32 pX, S32 pY, MASK pMask) +{ + BOOL returnVal = FALSE; + + if (mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask)) + { + computeFinalPoints(pX, pY, pMask); + setMouseCapture(FALSE); + returnVal = TRUE; + } + mIsLeftMouseButtonHeld = false; + + return returnVal; +} + +BOOL LLPathfindingPathTool::handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask) +{ + setMouseCapture(TRUE); + mIsMiddleMouseButtonHeld = true; + gViewerWindow->setCursor(UI_CURSOR_TOOLNO); + + return TRUE; +} + +BOOL LLPathfindingPathTool::handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask) +{ + if (!mIsLeftMouseButtonHeld && mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld) + { + setMouseCapture(FALSE); + } + mIsMiddleMouseButtonHeld = false; + + return TRUE; +} + +BOOL LLPathfindingPathTool::handleRightMouseDown(S32 pX, S32 pY, MASK pMask) +{ + setMouseCapture(TRUE); + mIsRightMouseButtonHeld = true; + gViewerWindow->setCursor(UI_CURSOR_TOOLNO); + + return TRUE; +} + +BOOL LLPathfindingPathTool::handleRightMouseUp(S32 pX, S32 pY, MASK pMask) +{ + if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && mIsRightMouseButtonHeld) + { + setMouseCapture(FALSE); + } + mIsRightMouseButtonHeld = false; + + return TRUE; +} + +BOOL LLPathfindingPathTool::handleDoubleClick(S32 pX, S32 pY, MASK pMask) +{ + return TRUE; +} + +BOOL LLPathfindingPathTool::handleHover(S32 pX, S32 pY, MASK pMask) +{ + BOOL returnVal = FALSE; + + if (!mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask)) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING); + computeTempPoints(pX, pY, pMask); + returnVal = TRUE; + } + else + { + clearTemp(); + computeFinalPath(); + } + + return returnVal; +} + +LLPathfindingPathTool::EPathStatus LLPathfindingPathTool::getPathStatus() const +{ + EPathStatus status = kPathStatusUnknown; + + if (LLPathingLib::getInstance() == NULL) + { + status = kPathStatusNotImplemented; + } + else if (!LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion()) + { + status = kPathStatusNotEnabled; + } + else if (!hasFinalA() && !hasFinalB()) + { + status = kPathStatusChooseStartAndEndPoints; + } + else if (!hasFinalA()) + { + status = kPathStatusChooseStartPoint; + } + else if (!hasFinalB()) + { + status = kPathStatusChooseEndPoint; + } + else if (mPathResult == LLPathingLib::LLPL_PATH_GENERATED_OK) + { + status = kPathStatusHasValidPath; + } + else if (mPathResult == LLPathingLib::LLPL_NO_PATH) + { + status = kPathStatusHasInvalidPath; + } + else + { + status = kPathStatusError; + } + + return status; +} + +F32 LLPathfindingPathTool::getCharacterWidth() const +{ + return mFinalPathData.mCharacterWidth; +} + +void LLPathfindingPathTool::setCharacterWidth(F32 pCharacterWidth) +{ + mFinalPathData.mCharacterWidth = pCharacterWidth; + mTempPathData.mCharacterWidth = pCharacterWidth; + computeFinalPath(); +} + +LLPathfindingPathTool::ECharacterType LLPathfindingPathTool::getCharacterType() const +{ + return mCharacterType; +} + +void LLPathfindingPathTool::setCharacterType(ECharacterType pCharacterType) +{ + mCharacterType = pCharacterType; + + LLPathingLib::LLPLCharacterType characterType; + switch (pCharacterType) + { + case kCharacterTypeNone : + characterType = LLPathingLib::LLPL_CHARACTER_TYPE_NONE; + break; + case kCharacterTypeA : + characterType = LLPathingLib::LLPL_CHARACTER_TYPE_A; + break; + case kCharacterTypeB : + characterType = LLPathingLib::LLPL_CHARACTER_TYPE_B; + break; + case kCharacterTypeC : + characterType = LLPathingLib::LLPL_CHARACTER_TYPE_C; + break; + case kCharacterTypeD : + characterType = LLPathingLib::LLPL_CHARACTER_TYPE_D; + break; + default : + characterType = LLPathingLib::LLPL_CHARACTER_TYPE_NONE; + llassert(0); + break; + } + mFinalPathData.mCharacterType = characterType; + mTempPathData.mCharacterType = characterType; + computeFinalPath(); +} + +bool LLPathfindingPathTool::isRenderPath() const +{ + return (hasFinalA() || hasFinalB() || hasTempA() || hasTempB()); +} + +void LLPathfindingPathTool::clearPath() +{ + clearFinal(); + clearTemp(); + computeFinalPath(); +} + +LLPathfindingPathTool::path_event_slot_t LLPathfindingPathTool::registerPathEventListener(path_event_callback_t pPathEventCallback) +{ + return mPathEventSignal.connect(pPathEventCallback); +} + +bool LLPathfindingPathTool::isAnyPathToolModKeys(MASK pMask) const +{ + return ((pMask & (MASK_CONTROL|MASK_SHIFT)) != 0); +} + +bool LLPathfindingPathTool::isPointAModKeys(MASK pMask) const +{ + return ((pMask & MASK_CONTROL) != 0); +} + +bool LLPathfindingPathTool::isPointBModKeys(MASK pMask) const +{ + return ((pMask & MASK_SHIFT) != 0); +} + +void LLPathfindingPathTool::getRayPoints(S32 pX, S32 pY, LLVector3 &pRayStart, LLVector3 &pRayEnd) const +{ + LLVector3 dv = gViewerWindow->mouseDirectionGlobal(pX, pY); + LLVector3 mousePos = LLViewerCamera::getInstance()->getOrigin(); + pRayStart = mousePos; + pRayEnd = mousePos + dv * 150; +} + +void LLPathfindingPathTool::computeFinalPoints(S32 pX, S32 pY, MASK pMask) +{ + LLVector3 rayStart, rayEnd; + getRayPoints(pX, pY, rayStart, rayEnd); + + if (isPointAModKeys(pMask)) + { + setFinalA(rayStart, rayEnd); + } + else if (isPointBModKeys(pMask)) + { + setFinalB(rayStart, rayEnd); + } + computeFinalPath(); +} + +void LLPathfindingPathTool::computeTempPoints(S32 pX, S32 pY, MASK pMask) +{ + LLVector3 rayStart, rayEnd; + getRayPoints(pX, pY, rayStart, rayEnd); + + if (isPointAModKeys(pMask)) + { + setTempA(rayStart, rayEnd); + if (hasFinalB()) + { + setTempB(getFinalBStart(), getFinalBEnd()); + } + } + else if (isPointBModKeys(pMask)) + { + if (hasFinalA()) + { + setTempA(getFinalAStart(), getFinalAEnd()); + } + setTempB(rayStart, rayEnd); + } + computeTempPath(); +} + +void LLPathfindingPathTool::setFinalA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) +{ + mFinalPathData.mStartPointA = pStartPoint; + mFinalPathData.mEndPointA = pEndPoint; + mFinalPathData.mHasPointA = true; +} + +bool LLPathfindingPathTool::hasFinalA() const +{ + return mFinalPathData.mHasPointA; +} + +const LLVector3 &LLPathfindingPathTool::getFinalAStart() const +{ + return mFinalPathData.mStartPointA; +} + +const LLVector3 &LLPathfindingPathTool::getFinalAEnd() const +{ + return mFinalPathData.mEndPointA; +} + +void LLPathfindingPathTool::setTempA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) +{ + mTempPathData.mStartPointA = pStartPoint; + mTempPathData.mEndPointA = pEndPoint; + mTempPathData.mHasPointA = true; +} + +bool LLPathfindingPathTool::hasTempA() const +{ + return mTempPathData.mHasPointA; +} + +void LLPathfindingPathTool::setFinalB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) +{ + mFinalPathData.mStartPointB = pStartPoint; + mFinalPathData.mEndPointB = pEndPoint; + mFinalPathData.mHasPointB = true; +} + +bool LLPathfindingPathTool::hasFinalB() const +{ + return mFinalPathData.mHasPointB; +} + +const LLVector3 &LLPathfindingPathTool::getFinalBStart() const +{ + return mFinalPathData.mStartPointB; +} + +const LLVector3 &LLPathfindingPathTool::getFinalBEnd() const +{ + return mFinalPathData.mEndPointB; +} + +void LLPathfindingPathTool::setTempB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint) +{ + mTempPathData.mStartPointB = pStartPoint; + mTempPathData.mEndPointB = pEndPoint; + mTempPathData.mHasPointB = true; +} + +bool LLPathfindingPathTool::hasTempB() const +{ + return mTempPathData.mHasPointB; +} + +void LLPathfindingPathTool::clearFinal() +{ + mFinalPathData.mHasPointA = false; + mFinalPathData.mHasPointB = false; +} + +void LLPathfindingPathTool::clearTemp() +{ + mTempPathData.mHasPointA = false; + mTempPathData.mHasPointB = false; +} + +void LLPathfindingPathTool::computeFinalPath() +{ + mPathResult = LLPathingLib::LLPL_NO_PATH; + if (LLPathingLib::getInstance() != NULL) + { + mPathResult = LLPathingLib::getInstance()->generatePath(mFinalPathData); + } + mPathEventSignal(); +} + +void LLPathfindingPathTool::computeTempPath() +{ + mPathResult = LLPathingLib::LLPL_NO_PATH; + if (LLPathingLib::getInstance() != NULL) + { + mPathResult = LLPathingLib::getInstance()->generatePath(mTempPathData); + } + mPathEventSignal(); +} diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h index 492304e4a4..0294111ccf 100644 --- a/indra/newview/llpathfindingpathtool.h +++ b/indra/newview/llpathfindingpathtool.h @@ -1,136 +1,136 @@ -/** - * @file llpathfindingpathtool.h - * @author William Todd Stinson - * @brief XXX - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPATHFINDINGPATHTOOL_H -#define LL_LLPATHFINDINGPATHTOOL_H - -#include "llsingleton.h" -#include "lltool.h" -#include "llpathinglib.h" - -#include -#include - -class LLPathfindingPathTool : public LLTool, public LLSingleton -{ -public: - typedef enum - { - kPathStatusUnknown, - kPathStatusChooseStartAndEndPoints, - kPathStatusChooseStartPoint, - kPathStatusChooseEndPoint, - kPathStatusHasValidPath, - kPathStatusHasInvalidPath, - kPathStatusNotEnabled, - kPathStatusNotImplemented, - kPathStatusError - } EPathStatus; - - typedef enum - { - kCharacterTypeNone, - kCharacterTypeA, - kCharacterTypeB, - kCharacterTypeC, - kCharacterTypeD - } ECharacterType; - - LLPathfindingPathTool(); - virtual ~LLPathfindingPathTool(); - - typedef boost::function path_event_callback_t; - typedef boost::signals2::signal path_event_signal_t; - typedef boost::signals2::connection path_event_slot_t; - - virtual BOOL handleMouseDown(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleMouseUp(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleRightMouseDown(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleRightMouseUp(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - - virtual BOOL handleHover(S32 pX, S32 pY, MASK pMask); - - EPathStatus getPathStatus() const; - - F32 getCharacterWidth() const; - void setCharacterWidth(F32 pCharacterWidth); - - ECharacterType getCharacterType() const; - void setCharacterType(ECharacterType pCharacterType); - - bool isRenderPath() const; - void clearPath(); - - path_event_slot_t registerPathEventListener(path_event_callback_t pPathEventCallback); - -protected: - -private: - bool isAnyPathToolModKeys(MASK pMask) const; - bool isPointAModKeys(MASK pMask) const; - bool isPointBModKeys(MASK pMask) const; - - void getRayPoints(S32 pX, S32 pY, LLVector3 &pRayStart, LLVector3 &pRayEnd) const; - void computeFinalPoints(S32 pX, S32 pY, MASK pMask); - void computeTempPoints(S32 pX, S32 pY, MASK pMask); - - void setFinalA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); - bool hasFinalA() const; - const LLVector3 &getFinalAStart() const; - const LLVector3 &getFinalAEnd() const; - - void setTempA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); - bool hasTempA() const; - - void setFinalB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); - bool hasFinalB() const; - const LLVector3 &getFinalBStart() const; - const LLVector3 &getFinalBEnd() const; - - void setTempB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); - bool hasTempB() const; - - void clearFinal(); - void clearTemp(); - - void computeFinalPath(); - void computeTempPath(); - - LLPathingLib::PathingPacket mFinalPathData; - LLPathingLib::PathingPacket mTempPathData; - LLPathingLib::LLPLResult mPathResult; - ECharacterType mCharacterType; - path_event_signal_t mPathEventSignal; - bool mIsLeftMouseButtonHeld; - bool mIsMiddleMouseButtonHeld; - bool mIsRightMouseButtonHeld; -}; - -#endif // LL_LLPATHFINDINGPATHTOOL_H +/** + * @file llpathfindingpathtool.h + * @author William Todd Stinson + * @brief XXX + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPATHFINDINGPATHTOOL_H +#define LL_LLPATHFINDINGPATHTOOL_H + +#include "llsingleton.h" +#include "lltool.h" +#include "llpathinglib.h" + +#include +#include + +class LLPathfindingPathTool : public LLTool, public LLSingleton +{ +public: + typedef enum + { + kPathStatusUnknown, + kPathStatusChooseStartAndEndPoints, + kPathStatusChooseStartPoint, + kPathStatusChooseEndPoint, + kPathStatusHasValidPath, + kPathStatusHasInvalidPath, + kPathStatusNotEnabled, + kPathStatusNotImplemented, + kPathStatusError + } EPathStatus; + + typedef enum + { + kCharacterTypeNone, + kCharacterTypeA, + kCharacterTypeB, + kCharacterTypeC, + kCharacterTypeD + } ECharacterType; + + LLPathfindingPathTool(); + virtual ~LLPathfindingPathTool(); + + typedef boost::function path_event_callback_t; + typedef boost::signals2::signal path_event_signal_t; + typedef boost::signals2::connection path_event_slot_t; + + virtual BOOL handleMouseDown(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleMouseUp(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleRightMouseDown(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleRightMouseUp(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + + virtual BOOL handleHover(S32 pX, S32 pY, MASK pMask); + + EPathStatus getPathStatus() const; + + F32 getCharacterWidth() const; + void setCharacterWidth(F32 pCharacterWidth); + + ECharacterType getCharacterType() const; + void setCharacterType(ECharacterType pCharacterType); + + bool isRenderPath() const; + void clearPath(); + + path_event_slot_t registerPathEventListener(path_event_callback_t pPathEventCallback); + +protected: + +private: + bool isAnyPathToolModKeys(MASK pMask) const; + bool isPointAModKeys(MASK pMask) const; + bool isPointBModKeys(MASK pMask) const; + + void getRayPoints(S32 pX, S32 pY, LLVector3 &pRayStart, LLVector3 &pRayEnd) const; + void computeFinalPoints(S32 pX, S32 pY, MASK pMask); + void computeTempPoints(S32 pX, S32 pY, MASK pMask); + + void setFinalA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); + bool hasFinalA() const; + const LLVector3 &getFinalAStart() const; + const LLVector3 &getFinalAEnd() const; + + void setTempA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); + bool hasTempA() const; + + void setFinalB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); + bool hasFinalB() const; + const LLVector3 &getFinalBStart() const; + const LLVector3 &getFinalBEnd() const; + + void setTempB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint); + bool hasTempB() const; + + void clearFinal(); + void clearTemp(); + + void computeFinalPath(); + void computeTempPath(); + + LLPathingLib::PathingPacket mFinalPathData; + LLPathingLib::PathingPacket mTempPathData; + LLPathingLib::LLPLResult mPathResult; + ECharacterType mCharacterType; + path_event_signal_t mPathEventSignal; + bool mIsLeftMouseButtonHeld; + bool mIsMiddleMouseButtonHeld; + bool mIsRightMouseButtonHeld; +}; + +#endif // LL_LLPATHFINDINGPATHTOOL_H diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 936bafb488..fbd8b3ada3 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1,1238 +1,1238 @@ -/** - * @file llworld.cpp - * @brief Initial test structure to organize viewer regions - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llworld.h" -#include "llrender.h" - -#include "indra_constants.h" -#include "llstl.h" - -#include "llagent.h" -#include "llviewercontrol.h" -#include "lldrawpool.h" -#include "llglheaders.h" -#include "llhttpnode.h" -#include "llregionhandle.h" -#include "llsurface.h" -#include "lltrans.h" -#include "llviewercamera.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llviewernetwork.h" -#include "llviewerobjectlist.h" -#include "llviewerparceloverlay.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llvlcomposition.h" -#include "llvoavatar.h" -#include "llvocache.h" -#include "llvowater.h" -#include "message.h" -#include "pipeline.h" -#include "llappviewer.h" // for do_disconnect() - -#include -#include -#include -#include - - -// -// Globals -// -U32 gAgentPauseSerialNum = 0; - -// -// Constants -// -const S32 MAX_NUMBER_OF_CLOUDS = 750; -const S32 WORLD_PATCH_SIZE = 16; - -extern LLColor4U MAX_WATER_COLOR; - -const U32 LLWorld::mWidth = 256; - -// meters/point, therefore mWidth * mScale = meters per edge -const F32 LLWorld::mScale = 1.f; - -const F32 LLWorld::mWidthInMeters = mWidth * mScale; - -// -// Functions -// - -// allocate the stack -LLWorld::LLWorld() : - mLandFarClip(DEFAULT_FAR_PLANE), - mLastPacketsIn(0), - mLastPacketsOut(0), - mLastPacketsLost(0), - mSpaceTimeUSec(0) -{ - for (S32 i = 0; i < 8; i++) - { - mEdgeWaterObjects[i] = NULL; - } - - LLPointer raw = new LLImageRaw(1,1,4); - U8 *default_texture = raw->getData(); - *(default_texture++) = MAX_WATER_COLOR.mV[0]; - *(default_texture++) = MAX_WATER_COLOR.mV[1]; - *(default_texture++) = MAX_WATER_COLOR.mV[2]; - *(default_texture++) = MAX_WATER_COLOR.mV[3]; - - mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); - gGL.getTexUnit(0)->bind(mDefaultWaterTexturep); - mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - -} - - -void LLWorld::destroyClass() -{ - mHoleWaterObjects.clear(); - gObjectList.destroy(); - for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); ) - { - LLViewerRegion* region_to_delete = *region_it++; - removeRegion(region_to_delete->getHost()); - } - if(LLVOCache::hasInstance()) - { - LLVOCache::getInstance()->destroyClass() ; - } - LLViewerPartSim::getInstance()->destroyClass(); - - mDefaultWaterTexturep = NULL ; - for (S32 i = 0; i < 8; i++) - { - mEdgeWaterObjects[i] = NULL; - } -} - - -LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) -{ - LLMemType mt(LLMemType::MTYPE_REGIONS); - llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl; - LLViewerRegion *regionp = getRegionFromHandle(region_handle); - if (regionp) - { - llinfos << "Region exists, removing it " << llendl; - LLHost old_host = regionp->getHost(); - // region already exists! - if (host == old_host && regionp->isAlive()) - { - // This is a duplicate for the same host and it's alive, don't bother. - return regionp; - } - - if (host != old_host) - { - llwarns << "LLWorld::addRegion exists, but old host " << old_host - << " does not match new host " << host << llendl; - } - if (!regionp->isAlive()) - { - llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl; - } - - // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host - // matches, because all the agent state for the new camera is completely different. - removeRegion(old_host); - } - - U32 iindex = 0; - U32 jindex = 0; - from_region_handle(region_handle, &iindex, &jindex); - S32 x = (S32)(iindex/mWidth); - S32 y = (S32)(jindex/mWidth); - llinfos << "Adding new region (" << x << ":" << y << ")" << llendl; - llinfos << "Host: " << host << llendl; - - LLVector3d origin_global; - - origin_global = from_region_handle(region_handle); - - regionp = new LLViewerRegion(region_handle, - host, - mWidth, - WORLD_PATCH_SIZE, - getRegionWidthInMeters() ); - if (!regionp) - { - llerrs << "Unable to create new region!" << llendl; - } - - mRegionList.push_back(regionp); - mActiveRegionList.push_back(regionp); - mCulledRegionList.push_back(regionp); - - - // Find all the adjacent regions, and attach them. - // Generate handles for all of the adjacent regions, and attach them in the correct way. - // connect the edges - F32 adj_x = 0.f; - F32 adj_y = 0.f; - F32 region_x = 0.f; - F32 region_y = 0.f; - U64 adj_handle = 0; - - F32 width = getRegionWidthInMeters(); - - LLViewerRegion *neighborp; - from_region_handle(region_handle, ®ion_x, ®ion_y); - - // Iterate through all directions, and connect neighbors if there. - S32 dir; - for (dir = 0; dir < 8; dir++) - { - adj_x = region_x + width * gDirAxes[dir][0]; - adj_y = region_y + width * gDirAxes[dir][1]; - to_region_handle(adj_x, adj_y, &adj_handle); - - neighborp = getRegionFromHandle(adj_handle); - if (neighborp) - { - //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl; - regionp->connectNeighbor(neighborp, dir); - } - } - - updateWaterObjects(); - - return regionp; -} - - -void LLWorld::removeRegion(const LLHost &host) -{ - F32 x, y; - - LLViewerRegion *regionp = getRegion(host); - if (!regionp) - { - llwarns << "Trying to remove region that doesn't exist!" << llendl; - return; - } - - if (regionp == gAgent.getRegion()) - { - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* reg = *iter; - llwarns << "RegionDump: " << reg->getName() - << " " << reg->getHost() - << " " << reg->getOriginGlobal() - << llendl; - } - - llwarns << "Agent position global " << gAgent.getPositionGlobal() - << " agent " << gAgent.getPositionAgent() - << llendl; - - llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl; - - llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; - - llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; - LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected")); - - regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed. - return; - } - - from_region_handle(regionp->getHandle(), &x, &y); - llinfos << "Removing region " << x << ":" << y << llendl; - - mRegionList.remove(regionp); - mActiveRegionList.remove(regionp); - mCulledRegionList.remove(regionp); - mVisibleRegionList.remove(regionp); - - delete regionp; - - updateWaterObjects(); - - //double check all objects of this region are removed. - gObjectList.clearAllMapObjectsInRegion(regionp) ; - //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; -} - - -LLViewerRegion* LLWorld::getRegion(const LLHost &host) -{ - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - if (regionp->getHost() == host) - { - return regionp; - } - } - return NULL; -} - -LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos) -{ - return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos)); -} - -LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos) -{ - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - if (regionp->pointInRegionGlobal(pos)) - { - return regionp; - } - } - return NULL; -} - - -LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) -{ - if (positionRegionValidGlobal(end_pos)) - { - return end_pos; - } - - LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); - if (!regionp) - { - return start_pos; - } - - LLVector3d delta_pos = end_pos - start_pos; - LLVector3d delta_pos_abs; - delta_pos_abs.setVec(delta_pos); - delta_pos_abs.abs(); - - LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); - F64 clip_factor = 1.0; - F32 region_width = regionp->getWidth(); - if (region_coord.mV[VX] < 0.f) - { - if (region_coord.mV[VY] < region_coord.mV[VX]) - { - // clip along y - - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); - } - else - { - // clip along x - - clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); - } - } - else if (region_coord.mV[VX] > region_width) - { - if (region_coord.mV[VY] > region_coord.mV[VX]) - { - // clip along y + - clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; - } - else - { - //clip along x + - clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; - } - } - else if (region_coord.mV[VY] < 0.f) - { - // clip along y - - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); - } - else if (region_coord.mV[VY] > region_width) - { - // clip along y + - clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; - } - - // clamp to within region dimensions - LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); - final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0, - (F64)(region_width - F_ALMOST_ZERO)); - final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0, - (F64)(region_width - F_ALMOST_ZERO)); - final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0, - (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO)); - return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); -} - -LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle) -{ - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - if (regionp->getHandle() == handle) - { - return regionp; - } - } - return NULL; -} - - -void LLWorld::updateAgentOffset(const LLVector3d &offset_global) -{ -#if 0 - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - regionp->setAgentOffset(offset_global); - } -#endif -} - - -BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global) -{ - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - if (regionp->pointInRegionGlobal(pos_global)) - { - return TRUE; - } - } - return FALSE; -} - - -// Allow objects to go up to their radius underground. -F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos) -{ - F32 land_height = resolveLandHeightGlobal(global_pos); - F32 radius = 0.5f * object->getScale().length(); - return land_height - radius; -} - - - -LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global) -{ - LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - - if (regionp) - { - pos_region = regionp->getPosRegionFromGlobal(pos_global); - return regionp; - } - - return NULL; -} - - -LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent) -{ - LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); - LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - - if (regionp) - { - pos_region = regionp->getPosRegionFromGlobal(pos_global); - return regionp; - } - - return NULL; -} - - -F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent) -{ - LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); - return resolveLandHeightGlobal(pos_global); -} - - -F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global) -{ - LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - if (regionp) - { - return regionp->getLand().resolveHeightGlobal(pos_global); - } - return 0.0f; -} - - -// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a) -// point where the the line intersects an object or the land surface. Stores the results -// in "intersection" and "intersection_normal" and returns a scalar value that represents -// the normalized distance along the line from "point_a" to "intersection". -// -// Currently assumes point_a and point_b only differ in z-direction, -// but it may eventually become more general. -F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b, - LLVector3d &intersection, LLVector3 &intersection_normal, - LLViewerObject **viewerObjectPtr) -{ - // initialize return value to null - if (viewerObjectPtr) - { - *viewerObjectPtr = NULL; - } - - LLViewerRegion *regionp = getRegionFromPosGlobal(point_a); - if (!regionp) - { - // We're outside the world - intersection = 0.5f * (point_a + point_b); - intersection_normal.setVec(0.0f, 0.0f, 1.0f); - return 0.5f; - } - - // calculate the length of the segment - F32 segment_length = (F32)((point_a - point_b).length()); - if (0.0f == segment_length) - { - intersection = point_a; - intersection_normal.setVec(0.0f, 0.0f, 1.0f); - return segment_length; - } - - // get land height - // Note: we assume that the line is parallel to z-axis here - LLVector3d land_intersection = point_a; - F32 normalized_land_distance; - - land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a); - normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length; - intersection = land_intersection; - intersection_normal = resolveLandNormalGlobal(land_intersection); - - if (avatarp && !avatarp->mFootPlane.isExactlyClear()) - { - LLVector3 foot_plane_normal(avatarp->mFootPlane.mV); - LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a); - // added 0.05 meters to compensate for error in foot plane reported by Havok - F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f; - norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f); - if (norm_dist_from_plane < normalized_land_distance) - { - // collided with object before land - normalized_land_distance = norm_dist_from_plane; - intersection = point_a; - intersection.mdV[VZ] -= norm_dist_from_plane * segment_length; - intersection_normal = foot_plane_normal; - } - else - { - intersection = land_intersection; - intersection_normal = resolveLandNormalGlobal(land_intersection); - } - } - - return normalized_land_distance; -} - - -LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) -{ - // returns a pointer to the patch at this location - LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - if (!regionp) - { - return NULL; - } - - return regionp->getLand().resolvePatchGlobal(pos_global); -} - - -LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global) -{ - LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - if (!regionp) - { - return LLVector3::z_axis; - } - - return regionp->getLand().resolveNormalGlobal(pos_global); -} - - -void LLWorld::updateVisibilities() -{ - F32 cur_far_clip = LLViewerCamera::getInstance()->getFar(); - - // Go through the culled list and check for visible regions (region is visible if land is visible) - for (region_list_t::iterator iter = mCulledRegionList.begin(); - iter != mCulledRegionList.end(); ) - { - region_list_t::iterator curiter = iter++; - LLViewerRegion* regionp = *curiter; - - LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); - if (part) - { - LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); - if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) - { - mCulledRegionList.erase(curiter); - mVisibleRegionList.push_back(regionp); - } - } - } - - // Update all of the visible regions - for (region_list_t::iterator iter = mVisibleRegionList.begin(); - iter != mVisibleRegionList.end(); ) - { - region_list_t::iterator curiter = iter++; - LLViewerRegion* regionp = *curiter; - if (!regionp->getLand().hasZData()) - { - continue; - } - - LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); - if (part) - { - LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); - if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) - { - regionp->calculateCameraDistance(); - regionp->getLand().updatePatchVisibilities(gAgent); - } - else - { - mVisibleRegionList.erase(curiter); - mCulledRegionList.push_back(regionp); - } - } - } - - // Sort visible regions - mVisibleRegionList.sort(LLViewerRegion::CompareDistance()); - - LLViewerCamera::getInstance()->setFar(cur_far_clip); -} - -void LLWorld::updateRegions(F32 max_update_time) -{ - LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS); - LLTimer update_timer; - BOOL did_one = FALSE; - - // Perform idle time updates for the regions (and associated surfaces) - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - F32 max_time = max_update_time - update_timer.getElapsedTimeF32(); - if (did_one && max_time <= 0.f) - break; - max_time = llmin(max_time, max_update_time*.1f); - did_one |= regionp->idleUpdate(max_update_time); - } -} - -void LLWorld::updateParticles() -{ - LLViewerPartSim::getInstance()->updateSimulation(); -} - -void LLWorld::renderPropertyLines() -{ - S32 region_count = 0; - S32 vertex_count = 0; - - for (region_list_t::iterator iter = mVisibleRegionList.begin(); - iter != mVisibleRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - region_count++; - vertex_count += regionp->renderPropertyLines(); - } -} - - -void LLWorld::updateNetStats() -{ - F32 bits = 0.f; - U32 packets = 0; - - for (region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - regionp->updateNetStats(); - bits += regionp->mBitStat.getCurrent(); - packets += llfloor( regionp->mPacketsStat.getCurrent() ); - } - - S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn; - S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut; - S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost; - - S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits(); - S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits(); - LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f); - LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f); - LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f); - LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in); - LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out); - LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); - if (packets_in) - { - LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); - } - else - { - LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f); - } - - mLastPacketsIn = gMessageSystem->mPacketsIn; - mLastPacketsOut = gMessageSystem->mPacketsOut; - mLastPacketsLost = gMessageSystem->mDroppedPackets; -} - - -void LLWorld::printPacketsLost() -{ - llinfos << "Simulators:" << llendl; - llinfos << "----------" << llendl; - - LLCircuitData *cdp = NULL; - for (region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost()); - if (cdp) - { - LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); - - llinfos << regionp->getHost() << ", range: " << range.length() - << " packets lost: " << cdp->getPacketsLost() << llendl; - } - } -} - -void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data) -{ - LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender()); - if( region ) - { - region->updateCoarseLocations(msg); - } -} - -F32 LLWorld::getLandFarClip() const -{ - return mLandFarClip; -} - -void LLWorld::setLandFarClip(const F32 far_clip) -{ - static S32 const rwidth = (S32)REGION_WIDTH_U32; - S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth; - S32 const n2 = (llceil(far_clip) - 1) / rwidth; - bool need_water_objects_update = n1 != n2; - - mLandFarClip = far_clip; - - if (need_water_objects_update) - { - updateWaterObjects(); - } -} - -// Some region that we're connected to, but not the one we're in, gave us -// a (possibly) new water height. Update it in our local copy. -void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height) -{ - for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter) - { - if ((*iter)->getName() == sim_name) - { - (*iter)->setWaterHeight(water_height); - break; - } - } -} - -void LLWorld::updateWaterObjects() -{ - if (!gAgent.getRegion()) - { - return; - } - if (mRegionList.empty()) - { - llwarns << "No regions!" << llendl; - return; - } - - // First, determine the min and max "box" of water objects - S32 min_x = 0; - S32 min_y = 0; - S32 max_x = 0; - S32 max_y = 0; - U32 region_x, region_y; - - S32 rwidth = 256; - - // We only want to fill in water for stuff that's near us, say, within 256 or 512m - S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256; - - LLViewerRegion* regionp = gAgent.getRegion(); - from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); - - min_x = (S32)region_x - range; - min_y = (S32)region_y - range; - max_x = (S32)region_x + range; - max_y = (S32)region_y + range; - - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - LLVOWater* waterp = regionp->getLand().getWaterObj(); - if (waterp) - { - gObjectList.updateActive(waterp); - } - } - - for (std::list::iterator iter = mHoleWaterObjects.begin(); - iter != mHoleWaterObjects.end(); ++ iter) - { - LLVOWater* waterp = *iter; - gObjectList.killObject(waterp); - } - mHoleWaterObjects.clear(); - - // Now, get a list of the holes - S32 x, y; - F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f; - for (x = min_x; x <= max_x; x += rwidth) - { - for (y = min_y; y <= max_y; y += rwidth) - { - U64 region_handle = to_region_handle(x, y); - if (!getRegionFromHandle(region_handle)) - { - LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); - waterp->setUseTexture(FALSE); - waterp->setPositionGlobal(LLVector3d(x + rwidth/2, - y + rwidth/2, - water_height)); - waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); - gPipeline.createObject(waterp); - mHoleWaterObjects.push_back(waterp); - } - } - } - - // Update edge water objects - S32 wx, wy; - S32 center_x, center_y; - wx = (max_x - min_x) + rwidth; - wy = (max_y - min_y) + rwidth; - center_x = min_x + (wx >> 1); - center_y = min_y + (wy >> 1); - - S32 add_boundary[4] = { - 512 - (max_x - region_x), - 512 - (max_y - region_y), - 512 - (region_x - min_x), - 512 - (region_y - min_y) }; - - S32 dir; - for (dir = 0; dir < 8; dir++) - { - S32 dim[2] = { 0 }; - switch (gDirAxes[dir][0]) - { - case -1: dim[0] = add_boundary[2]; break; - case 0: dim[0] = wx; break; - default: dim[0] = add_boundary[0]; break; - } - switch (gDirAxes[dir][1]) - { - case -1: dim[1] = add_boundary[3]; break; - case 0: dim[1] = wy; break; - default: dim[1] = add_boundary[1]; break; - } - - // Resize and reshape the water objects - const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); - const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); - - LLVOWater* waterp = mEdgeWaterObjects[dir]; - if (!waterp || waterp->isDead()) - { - // The edge water objects can be dead because they're attached to the region that the - // agent was in when they were originally created. - mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, - gAgent.getRegion()); - waterp = mEdgeWaterObjects[dir]; - waterp->setUseTexture(FALSE); - waterp->setIsEdgePatch(TRUE); - gPipeline.createObject(waterp); - } - - waterp->setRegion(gAgent.getRegion()); - LLVector3d water_pos(water_center_x, water_center_y, water_height) ; - LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); - - //stretch out to horizon - water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]); - water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]); - - water_pos.mdV[0] += 1024.f * gDirAxes[dir][0]; - water_pos.mdV[1] += 1024.f * gDirAxes[dir][1]; - - waterp->setPositionGlobal(water_pos); - waterp->setScale(water_scale); - - gObjectList.updateActive(waterp); - } -} - - -void LLWorld::shiftRegions(const LLVector3& offset) -{ - for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i) - { - LLViewerRegion* region = *i; - region->updateRenderMatrix(); - } - - LLViewerPartSim::getInstance()->shift(offset); -} - -LLViewerTexture* LLWorld::getDefaultWaterTexture() -{ - return mDefaultWaterTexturep; -} - -void LLWorld::setSpaceTimeUSec(const U64 space_time_usec) -{ - mSpaceTimeUSec = space_time_usec; -} - -U64 LLWorld::getSpaceTimeUSec() const -{ - return mSpaceTimeUSec; -} - -void LLWorld::requestCacheMisses() -{ - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - regionp->requestCacheMisses(); - } -} - -void LLWorld::getInfo(LLSD& info) -{ - LLSD region_info; - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - regionp->getInfo(region_info); - info["World"].append(region_info); - } -} - -void LLWorld::disconnectRegions() -{ - LLMessageSystem* msg = gMessageSystem; - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - if (regionp == gAgent.getRegion()) - { - // Skip the main agent - continue; - } - - llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl; - msg->newMessageFast(_PREHASH_AgentQuitCopy); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_FuseBlock); - msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode); - msg->sendMessage(regionp->getHost()); - } -} - -static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim"); - -void process_enable_simulator(LLMessageSystem *msg, void **user_data) -{ - LLFastTimer t(FTM_ENABLE_SIMULATOR); - // enable the appropriate circuit for this simulator and - // add its values into the gSimulator structure - U64 handle; - U32 ip_u32; - U16 port; - - msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle); - msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32); - msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port); - - // which simulator should we modify? - LLHost sim(ip_u32, port); - - // Viewer trusts the simulator. - msg->enableCircuit(sim, TRUE); - LLWorld::getInstance()->addRegion(handle, sim); - - // give the simulator a message it can use to get ip and port - llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl; - msg->newMessageFast(_PREHASH_UseCircuitCode); - msg->nextBlockFast(_PREHASH_CircuitCode); - msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); - msg->sendReliable(sim); -} - -class LLEstablishAgentCommunication : public LLHTTPNode -{ - LOG_CLASS(LLEstablishAgentCommunication); -public: - virtual void describe(Description& desc) const - { - desc.shortInfo("seed capability info for a region"); - desc.postAPI(); - desc.input( - "{ seed-capability: ..., sim-ip: ..., sim-port }"); - desc.source(__FILE__, __LINE__); - } - - virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const - { - if (!input["body"].has("agent-id") || - !input["body"].has("sim-ip-and-port") || - !input["body"].has("seed-capability")) - { - llwarns << "invalid parameters" << llendl; - return; - } - - LLHost sim(input["body"]["sim-ip-and-port"].asString()); - - LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim); - if (!regionp) - { - llwarns << "Got EstablishAgentCommunication for unknown region " - << sim << llendl; - return; - } - regionp->setSeedCapability(input["body"]["seed-capability"]); - } -}; - -// disable the circuit to this simulator -// Called in response to "DisableSimulator" message. -void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) -{ - LLHost host = mesgsys->getSender(); - - //llinfos << "Disabling simulator with message from " << host << llendl; - LLWorld::getInstance()->removeRegion(host); - - mesgsys->disableCircuit(host); -} - - -void process_region_handshake(LLMessageSystem* msg, void** user_data) -{ - LLHost host = msg->getSender(); - LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host); - if (!regionp) - { - llwarns << "Got region handshake for unknown region " - << host << llendl; - return; - } - - regionp->unpackRegionHandshake(); -} - - -void send_agent_pause() -{ - // *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause - // the thread monitor to timeout. - LLAppViewer::instance()->pauseMainloopTimeout(); - - // Note: used to check for LLWorld initialization before it became a singleton. - // Rather than just remove this check I'm changing it to assure that the message - // system has been initialized. -MG - if (!gMessageSystem) - { - return; - } - - gMessageSystem->newMessageFast(_PREHASH_AgentPause); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); - - gAgentPauseSerialNum++; - gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* regionp = *iter; - gMessageSystem->sendReliable(regionp->getHost()); - } - - gObjectList.mWasPaused = TRUE; -} - - -void send_agent_resume() -{ - // Note: used to check for LLWorld initialization before it became a singleton. - // Rather than just remove this check I'm changing it to assure that the message - // system has been initialized. -MG - if (!gMessageSystem) - { - return; - } - - gMessageSystem->newMessageFast(_PREHASH_AgentResume); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); - - gAgentPauseSerialNum++; - gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); - - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* regionp = *iter; - gMessageSystem->sendReliable(regionp->getHost()); - } - - // Reset the FPS counter to avoid an invalid fps - LLViewerStats::getInstance()->mFPSStat.start(); - - LLAppViewer::instance()->resumeMainloopTimeout(); -} - -static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin) -{ - LLVector3d pos_local; - - pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4; - pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU; - pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU; - - return region_origin + pos_local; -} - -void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector* positions, const LLVector3d& relative_to, F32 radius) const -{ - F32 radius_squared = radius * radius; - - if(avatar_ids != NULL) - { - avatar_ids->clear(); - } - if(positions != NULL) - { - positions->clear(); - } - // get the list of avatars from the character list first, so distances are correct - // when agent is above 1020m and other avatars are nearby - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; - LLVector3d pos_global = pVOAvatar->getPositionGlobal(); - LLUUID uuid = pVOAvatar->getID(); - if( !pVOAvatar->isDead() - && !pVOAvatar->isSelf() - && !uuid.isNull() && - dist_vec_squared(pos_global, relative_to) <= radius_squared) - { - if(positions != NULL) - { - positions->push_back(pos_global); - } - if(avatar_ids !=NULL) - { - avatar_ids->push_back(uuid); - } - } - } - // region avatars added for situations where radius is greater than RenderFarClip - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* regionp = *iter; - const LLVector3d& origin_global = regionp->getOriginGlobal(); - S32 count = regionp->mMapAvatars.count(); - for (S32 i = 0; i < count; i++) - { - LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); - if(dist_vec_squared(pos_global, relative_to) <= radius_squared) - { - LLUUID uuid = regionp->mMapAvatarIDs.get(i); - // if this avatar doesn't already exist in the list, add it - if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) - { - if (positions != NULL) - { - positions->push_back(pos_global); - } - avatar_ids->push_back(uuid); - } - } - } - } -} - - -LLHTTPRegistration - gHTTPRegistrationEstablishAgentCommunication( - "/message/EstablishAgentCommunication"); +/** + * @file llworld.cpp + * @brief Initial test structure to organize viewer regions + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llworld.h" +#include "llrender.h" + +#include "indra_constants.h" +#include "llstl.h" + +#include "llagent.h" +#include "llviewercontrol.h" +#include "lldrawpool.h" +#include "llglheaders.h" +#include "llhttpnode.h" +#include "llregionhandle.h" +#include "llsurface.h" +#include "lltrans.h" +#include "llviewercamera.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" +#include "llviewernetwork.h" +#include "llviewerobjectlist.h" +#include "llviewerparceloverlay.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llvlcomposition.h" +#include "llvoavatar.h" +#include "llvocache.h" +#include "llvowater.h" +#include "message.h" +#include "pipeline.h" +#include "llappviewer.h" // for do_disconnect() + +#include +#include +#include +#include + + +// +// Globals +// +U32 gAgentPauseSerialNum = 0; + +// +// Constants +// +const S32 MAX_NUMBER_OF_CLOUDS = 750; +const S32 WORLD_PATCH_SIZE = 16; + +extern LLColor4U MAX_WATER_COLOR; + +const U32 LLWorld::mWidth = 256; + +// meters/point, therefore mWidth * mScale = meters per edge +const F32 LLWorld::mScale = 1.f; + +const F32 LLWorld::mWidthInMeters = mWidth * mScale; + +// +// Functions +// + +// allocate the stack +LLWorld::LLWorld() : + mLandFarClip(DEFAULT_FAR_PLANE), + mLastPacketsIn(0), + mLastPacketsOut(0), + mLastPacketsLost(0), + mSpaceTimeUSec(0) +{ + for (S32 i = 0; i < 8; i++) + { + mEdgeWaterObjects[i] = NULL; + } + + LLPointer raw = new LLImageRaw(1,1,4); + U8 *default_texture = raw->getData(); + *(default_texture++) = MAX_WATER_COLOR.mV[0]; + *(default_texture++) = MAX_WATER_COLOR.mV[1]; + *(default_texture++) = MAX_WATER_COLOR.mV[2]; + *(default_texture++) = MAX_WATER_COLOR.mV[3]; + + mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + gGL.getTexUnit(0)->bind(mDefaultWaterTexturep); + mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + +} + + +void LLWorld::destroyClass() +{ + mHoleWaterObjects.clear(); + gObjectList.destroy(); + for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); ) + { + LLViewerRegion* region_to_delete = *region_it++; + removeRegion(region_to_delete->getHost()); + } + if(LLVOCache::hasInstance()) + { + LLVOCache::getInstance()->destroyClass() ; + } + LLViewerPartSim::getInstance()->destroyClass(); + + mDefaultWaterTexturep = NULL ; + for (S32 i = 0; i < 8; i++) + { + mEdgeWaterObjects[i] = NULL; + } +} + + +LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) +{ + LLMemType mt(LLMemType::MTYPE_REGIONS); + llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl; + LLViewerRegion *regionp = getRegionFromHandle(region_handle); + if (regionp) + { + llinfos << "Region exists, removing it " << llendl; + LLHost old_host = regionp->getHost(); + // region already exists! + if (host == old_host && regionp->isAlive()) + { + // This is a duplicate for the same host and it's alive, don't bother. + return regionp; + } + + if (host != old_host) + { + llwarns << "LLWorld::addRegion exists, but old host " << old_host + << " does not match new host " << host << llendl; + } + if (!regionp->isAlive()) + { + llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl; + } + + // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host + // matches, because all the agent state for the new camera is completely different. + removeRegion(old_host); + } + + U32 iindex = 0; + U32 jindex = 0; + from_region_handle(region_handle, &iindex, &jindex); + S32 x = (S32)(iindex/mWidth); + S32 y = (S32)(jindex/mWidth); + llinfos << "Adding new region (" << x << ":" << y << ")" << llendl; + llinfos << "Host: " << host << llendl; + + LLVector3d origin_global; + + origin_global = from_region_handle(region_handle); + + regionp = new LLViewerRegion(region_handle, + host, + mWidth, + WORLD_PATCH_SIZE, + getRegionWidthInMeters() ); + if (!regionp) + { + llerrs << "Unable to create new region!" << llendl; + } + + mRegionList.push_back(regionp); + mActiveRegionList.push_back(regionp); + mCulledRegionList.push_back(regionp); + + + // Find all the adjacent regions, and attach them. + // Generate handles for all of the adjacent regions, and attach them in the correct way. + // connect the edges + F32 adj_x = 0.f; + F32 adj_y = 0.f; + F32 region_x = 0.f; + F32 region_y = 0.f; + U64 adj_handle = 0; + + F32 width = getRegionWidthInMeters(); + + LLViewerRegion *neighborp; + from_region_handle(region_handle, ®ion_x, ®ion_y); + + // Iterate through all directions, and connect neighbors if there. + S32 dir; + for (dir = 0; dir < 8; dir++) + { + adj_x = region_x + width * gDirAxes[dir][0]; + adj_y = region_y + width * gDirAxes[dir][1]; + to_region_handle(adj_x, adj_y, &adj_handle); + + neighborp = getRegionFromHandle(adj_handle); + if (neighborp) + { + //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl; + regionp->connectNeighbor(neighborp, dir); + } + } + + updateWaterObjects(); + + return regionp; +} + + +void LLWorld::removeRegion(const LLHost &host) +{ + F32 x, y; + + LLViewerRegion *regionp = getRegion(host); + if (!regionp) + { + llwarns << "Trying to remove region that doesn't exist!" << llendl; + return; + } + + if (regionp == gAgent.getRegion()) + { + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* reg = *iter; + llwarns << "RegionDump: " << reg->getName() + << " " << reg->getHost() + << " " << reg->getOriginGlobal() + << llendl; + } + + llwarns << "Agent position global " << gAgent.getPositionGlobal() + << " agent " << gAgent.getPositionAgent() + << llendl; + + llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl; + + llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; + + llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected")); + + regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed. + return; + } + + from_region_handle(regionp->getHandle(), &x, &y); + llinfos << "Removing region " << x << ":" << y << llendl; + + mRegionList.remove(regionp); + mActiveRegionList.remove(regionp); + mCulledRegionList.remove(regionp); + mVisibleRegionList.remove(regionp); + + delete regionp; + + updateWaterObjects(); + + //double check all objects of this region are removed. + gObjectList.clearAllMapObjectsInRegion(regionp) ; + //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; +} + + +LLViewerRegion* LLWorld::getRegion(const LLHost &host) +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp->getHost() == host) + { + return regionp; + } + } + return NULL; +} + +LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos) +{ + return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos)); +} + +LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos) +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp->pointInRegionGlobal(pos)) + { + return regionp; + } + } + return NULL; +} + + +LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) +{ + if (positionRegionValidGlobal(end_pos)) + { + return end_pos; + } + + LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); + if (!regionp) + { + return start_pos; + } + + LLVector3d delta_pos = end_pos - start_pos; + LLVector3d delta_pos_abs; + delta_pos_abs.setVec(delta_pos); + delta_pos_abs.abs(); + + LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); + F64 clip_factor = 1.0; + F32 region_width = regionp->getWidth(); + if (region_coord.mV[VX] < 0.f) + { + if (region_coord.mV[VY] < region_coord.mV[VX]) + { + // clip along y - + clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); + } + else + { + // clip along x - + clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); + } + } + else if (region_coord.mV[VX] > region_width) + { + if (region_coord.mV[VY] > region_coord.mV[VX]) + { + // clip along y + + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; + } + else + { + //clip along x + + clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; + } + } + else if (region_coord.mV[VY] < 0.f) + { + // clip along y - + clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); + } + else if (region_coord.mV[VY] > region_width) + { + // clip along y + + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; + } + + // clamp to within region dimensions + LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); + final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0, + (F64)(region_width - F_ALMOST_ZERO)); + final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0, + (F64)(region_width - F_ALMOST_ZERO)); + final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0, + (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO)); + return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); +} + +LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle) +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp->getHandle() == handle) + { + return regionp; + } + } + return NULL; +} + + +void LLWorld::updateAgentOffset(const LLVector3d &offset_global) +{ +#if 0 + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + regionp->setAgentOffset(offset_global); + } +#endif +} + + +BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global) +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp->pointInRegionGlobal(pos_global)) + { + return TRUE; + } + } + return FALSE; +} + + +// Allow objects to go up to their radius underground. +F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos) +{ + F32 land_height = resolveLandHeightGlobal(global_pos); + F32 radius = 0.5f * object->getScale().length(); + return land_height - radius; +} + + + +LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global) +{ + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + + if (regionp) + { + pos_region = regionp->getPosRegionFromGlobal(pos_global); + return regionp; + } + + return NULL; +} + + +LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent) +{ + LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + + if (regionp) + { + pos_region = regionp->getPosRegionFromGlobal(pos_global); + return regionp; + } + + return NULL; +} + + +F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent) +{ + LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); + return resolveLandHeightGlobal(pos_global); +} + + +F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global) +{ + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + if (regionp) + { + return regionp->getLand().resolveHeightGlobal(pos_global); + } + return 0.0f; +} + + +// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a) +// point where the the line intersects an object or the land surface. Stores the results +// in "intersection" and "intersection_normal" and returns a scalar value that represents +// the normalized distance along the line from "point_a" to "intersection". +// +// Currently assumes point_a and point_b only differ in z-direction, +// but it may eventually become more general. +F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b, + LLVector3d &intersection, LLVector3 &intersection_normal, + LLViewerObject **viewerObjectPtr) +{ + // initialize return value to null + if (viewerObjectPtr) + { + *viewerObjectPtr = NULL; + } + + LLViewerRegion *regionp = getRegionFromPosGlobal(point_a); + if (!regionp) + { + // We're outside the world + intersection = 0.5f * (point_a + point_b); + intersection_normal.setVec(0.0f, 0.0f, 1.0f); + return 0.5f; + } + + // calculate the length of the segment + F32 segment_length = (F32)((point_a - point_b).length()); + if (0.0f == segment_length) + { + intersection = point_a; + intersection_normal.setVec(0.0f, 0.0f, 1.0f); + return segment_length; + } + + // get land height + // Note: we assume that the line is parallel to z-axis here + LLVector3d land_intersection = point_a; + F32 normalized_land_distance; + + land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a); + normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length; + intersection = land_intersection; + intersection_normal = resolveLandNormalGlobal(land_intersection); + + if (avatarp && !avatarp->mFootPlane.isExactlyClear()) + { + LLVector3 foot_plane_normal(avatarp->mFootPlane.mV); + LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a); + // added 0.05 meters to compensate for error in foot plane reported by Havok + F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f; + norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f); + if (norm_dist_from_plane < normalized_land_distance) + { + // collided with object before land + normalized_land_distance = norm_dist_from_plane; + intersection = point_a; + intersection.mdV[VZ] -= norm_dist_from_plane * segment_length; + intersection_normal = foot_plane_normal; + } + else + { + intersection = land_intersection; + intersection_normal = resolveLandNormalGlobal(land_intersection); + } + } + + return normalized_land_distance; +} + + +LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) +{ + // returns a pointer to the patch at this location + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + if (!regionp) + { + return NULL; + } + + return regionp->getLand().resolvePatchGlobal(pos_global); +} + + +LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global) +{ + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + if (!regionp) + { + return LLVector3::z_axis; + } + + return regionp->getLand().resolveNormalGlobal(pos_global); +} + + +void LLWorld::updateVisibilities() +{ + F32 cur_far_clip = LLViewerCamera::getInstance()->getFar(); + + // Go through the culled list and check for visible regions (region is visible if land is visible) + for (region_list_t::iterator iter = mCulledRegionList.begin(); + iter != mCulledRegionList.end(); ) + { + region_list_t::iterator curiter = iter++; + LLViewerRegion* regionp = *curiter; + + LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); + if (part) + { + LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); + if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + { + mCulledRegionList.erase(curiter); + mVisibleRegionList.push_back(regionp); + } + } + } + + // Update all of the visible regions + for (region_list_t::iterator iter = mVisibleRegionList.begin(); + iter != mVisibleRegionList.end(); ) + { + region_list_t::iterator curiter = iter++; + LLViewerRegion* regionp = *curiter; + if (!regionp->getLand().hasZData()) + { + continue; + } + + LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); + if (part) + { + LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); + if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + { + regionp->calculateCameraDistance(); + regionp->getLand().updatePatchVisibilities(gAgent); + } + else + { + mVisibleRegionList.erase(curiter); + mCulledRegionList.push_back(regionp); + } + } + } + + // Sort visible regions + mVisibleRegionList.sort(LLViewerRegion::CompareDistance()); + + LLViewerCamera::getInstance()->setFar(cur_far_clip); +} + +void LLWorld::updateRegions(F32 max_update_time) +{ + LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS); + LLTimer update_timer; + BOOL did_one = FALSE; + + // Perform idle time updates for the regions (and associated surfaces) + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + F32 max_time = max_update_time - update_timer.getElapsedTimeF32(); + if (did_one && max_time <= 0.f) + break; + max_time = llmin(max_time, max_update_time*.1f); + did_one |= regionp->idleUpdate(max_update_time); + } +} + +void LLWorld::updateParticles() +{ + LLViewerPartSim::getInstance()->updateSimulation(); +} + +void LLWorld::renderPropertyLines() +{ + S32 region_count = 0; + S32 vertex_count = 0; + + for (region_list_t::iterator iter = mVisibleRegionList.begin(); + iter != mVisibleRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + region_count++; + vertex_count += regionp->renderPropertyLines(); + } +} + + +void LLWorld::updateNetStats() +{ + F32 bits = 0.f; + U32 packets = 0; + + for (region_list_t::iterator iter = mActiveRegionList.begin(); + iter != mActiveRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + regionp->updateNetStats(); + bits += regionp->mBitStat.getCurrent(); + packets += llfloor( regionp->mPacketsStat.getCurrent() ); + } + + S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn; + S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut; + S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost; + + S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits(); + S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits(); + LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f); + LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f); + LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f); + LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in); + LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out); + LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); + if (packets_in) + { + LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); + } + else + { + LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f); + } + + mLastPacketsIn = gMessageSystem->mPacketsIn; + mLastPacketsOut = gMessageSystem->mPacketsOut; + mLastPacketsLost = gMessageSystem->mDroppedPackets; +} + + +void LLWorld::printPacketsLost() +{ + llinfos << "Simulators:" << llendl; + llinfos << "----------" << llendl; + + LLCircuitData *cdp = NULL; + for (region_list_t::iterator iter = mActiveRegionList.begin(); + iter != mActiveRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost()); + if (cdp) + { + LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); + + llinfos << regionp->getHost() << ", range: " << range.length() + << " packets lost: " << cdp->getPacketsLost() << llendl; + } + } +} + +void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data) +{ + LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender()); + if( region ) + { + region->updateCoarseLocations(msg); + } +} + +F32 LLWorld::getLandFarClip() const +{ + return mLandFarClip; +} + +void LLWorld::setLandFarClip(const F32 far_clip) +{ + static S32 const rwidth = (S32)REGION_WIDTH_U32; + S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth; + S32 const n2 = (llceil(far_clip) - 1) / rwidth; + bool need_water_objects_update = n1 != n2; + + mLandFarClip = far_clip; + + if (need_water_objects_update) + { + updateWaterObjects(); + } +} + +// Some region that we're connected to, but not the one we're in, gave us +// a (possibly) new water height. Update it in our local copy. +void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height) +{ + for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter) + { + if ((*iter)->getName() == sim_name) + { + (*iter)->setWaterHeight(water_height); + break; + } + } +} + +void LLWorld::updateWaterObjects() +{ + if (!gAgent.getRegion()) + { + return; + } + if (mRegionList.empty()) + { + llwarns << "No regions!" << llendl; + return; + } + + // First, determine the min and max "box" of water objects + S32 min_x = 0; + S32 min_y = 0; + S32 max_x = 0; + S32 max_y = 0; + U32 region_x, region_y; + + S32 rwidth = 256; + + // We only want to fill in water for stuff that's near us, say, within 256 or 512m + S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256; + + LLViewerRegion* regionp = gAgent.getRegion(); + from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); + + min_x = (S32)region_x - range; + min_y = (S32)region_y - range; + max_x = (S32)region_x + range; + max_y = (S32)region_y + range; + + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + LLVOWater* waterp = regionp->getLand().getWaterObj(); + if (waterp) + { + gObjectList.updateActive(waterp); + } + } + + for (std::list::iterator iter = mHoleWaterObjects.begin(); + iter != mHoleWaterObjects.end(); ++ iter) + { + LLVOWater* waterp = *iter; + gObjectList.killObject(waterp); + } + mHoleWaterObjects.clear(); + + // Now, get a list of the holes + S32 x, y; + F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f; + for (x = min_x; x <= max_x; x += rwidth) + { + for (y = min_y; y <= max_y; y += rwidth) + { + U64 region_handle = to_region_handle(x, y); + if (!getRegionFromHandle(region_handle)) + { + LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); + waterp->setUseTexture(FALSE); + waterp->setPositionGlobal(LLVector3d(x + rwidth/2, + y + rwidth/2, + water_height)); + waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); + gPipeline.createObject(waterp); + mHoleWaterObjects.push_back(waterp); + } + } + } + + // Update edge water objects + S32 wx, wy; + S32 center_x, center_y; + wx = (max_x - min_x) + rwidth; + wy = (max_y - min_y) + rwidth; + center_x = min_x + (wx >> 1); + center_y = min_y + (wy >> 1); + + S32 add_boundary[4] = { + 512 - (max_x - region_x), + 512 - (max_y - region_y), + 512 - (region_x - min_x), + 512 - (region_y - min_y) }; + + S32 dir; + for (dir = 0; dir < 8; dir++) + { + S32 dim[2] = { 0 }; + switch (gDirAxes[dir][0]) + { + case -1: dim[0] = add_boundary[2]; break; + case 0: dim[0] = wx; break; + default: dim[0] = add_boundary[0]; break; + } + switch (gDirAxes[dir][1]) + { + case -1: dim[1] = add_boundary[3]; break; + case 0: dim[1] = wy; break; + default: dim[1] = add_boundary[1]; break; + } + + // Resize and reshape the water objects + const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); + const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); + + LLVOWater* waterp = mEdgeWaterObjects[dir]; + if (!waterp || waterp->isDead()) + { + // The edge water objects can be dead because they're attached to the region that the + // agent was in when they were originally created. + mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, + gAgent.getRegion()); + waterp = mEdgeWaterObjects[dir]; + waterp->setUseTexture(FALSE); + waterp->setIsEdgePatch(TRUE); + gPipeline.createObject(waterp); + } + + waterp->setRegion(gAgent.getRegion()); + LLVector3d water_pos(water_center_x, water_center_y, water_height) ; + LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); + + //stretch out to horizon + water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]); + water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]); + + water_pos.mdV[0] += 1024.f * gDirAxes[dir][0]; + water_pos.mdV[1] += 1024.f * gDirAxes[dir][1]; + + waterp->setPositionGlobal(water_pos); + waterp->setScale(water_scale); + + gObjectList.updateActive(waterp); + } +} + + +void LLWorld::shiftRegions(const LLVector3& offset) +{ + for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i) + { + LLViewerRegion* region = *i; + region->updateRenderMatrix(); + } + + LLViewerPartSim::getInstance()->shift(offset); +} + +LLViewerTexture* LLWorld::getDefaultWaterTexture() +{ + return mDefaultWaterTexturep; +} + +void LLWorld::setSpaceTimeUSec(const U64 space_time_usec) +{ + mSpaceTimeUSec = space_time_usec; +} + +U64 LLWorld::getSpaceTimeUSec() const +{ + return mSpaceTimeUSec; +} + +void LLWorld::requestCacheMisses() +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + regionp->requestCacheMisses(); + } +} + +void LLWorld::getInfo(LLSD& info) +{ + LLSD region_info; + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + regionp->getInfo(region_info); + info["World"].append(region_info); + } +} + +void LLWorld::disconnectRegions() +{ + LLMessageSystem* msg = gMessageSystem; + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp == gAgent.getRegion()) + { + // Skip the main agent + continue; + } + + llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl; + msg->newMessageFast(_PREHASH_AgentQuitCopy); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FuseBlock); + msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode); + msg->sendMessage(regionp->getHost()); + } +} + +static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim"); + +void process_enable_simulator(LLMessageSystem *msg, void **user_data) +{ + LLFastTimer t(FTM_ENABLE_SIMULATOR); + // enable the appropriate circuit for this simulator and + // add its values into the gSimulator structure + U64 handle; + U32 ip_u32; + U16 port; + + msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle); + msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32); + msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port); + + // which simulator should we modify? + LLHost sim(ip_u32, port); + + // Viewer trusts the simulator. + msg->enableCircuit(sim, TRUE); + LLWorld::getInstance()->addRegion(handle, sim); + + // give the simulator a message it can use to get ip and port + llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl; + msg->newMessageFast(_PREHASH_UseCircuitCode); + msg->nextBlockFast(_PREHASH_CircuitCode); + msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); + msg->sendReliable(sim); +} + +class LLEstablishAgentCommunication : public LLHTTPNode +{ + LOG_CLASS(LLEstablishAgentCommunication); +public: + virtual void describe(Description& desc) const + { + desc.shortInfo("seed capability info for a region"); + desc.postAPI(); + desc.input( + "{ seed-capability: ..., sim-ip: ..., sim-port }"); + desc.source(__FILE__, __LINE__); + } + + virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const + { + if (!input["body"].has("agent-id") || + !input["body"].has("sim-ip-and-port") || + !input["body"].has("seed-capability")) + { + llwarns << "invalid parameters" << llendl; + return; + } + + LLHost sim(input["body"]["sim-ip-and-port"].asString()); + + LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim); + if (!regionp) + { + llwarns << "Got EstablishAgentCommunication for unknown region " + << sim << llendl; + return; + } + regionp->setSeedCapability(input["body"]["seed-capability"]); + } +}; + +// disable the circuit to this simulator +// Called in response to "DisableSimulator" message. +void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) +{ + LLHost host = mesgsys->getSender(); + + //llinfos << "Disabling simulator with message from " << host << llendl; + LLWorld::getInstance()->removeRegion(host); + + mesgsys->disableCircuit(host); +} + + +void process_region_handshake(LLMessageSystem* msg, void** user_data) +{ + LLHost host = msg->getSender(); + LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host); + if (!regionp) + { + llwarns << "Got region handshake for unknown region " + << host << llendl; + return; + } + + regionp->unpackRegionHandshake(); +} + + +void send_agent_pause() +{ + // *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause + // the thread monitor to timeout. + LLAppViewer::instance()->pauseMainloopTimeout(); + + // Note: used to check for LLWorld initialization before it became a singleton. + // Rather than just remove this check I'm changing it to assure that the message + // system has been initialized. -MG + if (!gMessageSystem) + { + return; + } + + gMessageSystem->newMessageFast(_PREHASH_AgentPause); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + + gAgentPauseSerialNum++; + gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* regionp = *iter; + gMessageSystem->sendReliable(regionp->getHost()); + } + + gObjectList.mWasPaused = TRUE; +} + + +void send_agent_resume() +{ + // Note: used to check for LLWorld initialization before it became a singleton. + // Rather than just remove this check I'm changing it to assure that the message + // system has been initialized. -MG + if (!gMessageSystem) + { + return; + } + + gMessageSystem->newMessageFast(_PREHASH_AgentResume); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + + gAgentPauseSerialNum++; + gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); + + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* regionp = *iter; + gMessageSystem->sendReliable(regionp->getHost()); + } + + // Reset the FPS counter to avoid an invalid fps + LLViewerStats::getInstance()->mFPSStat.start(); + + LLAppViewer::instance()->resumeMainloopTimeout(); +} + +static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin) +{ + LLVector3d pos_local; + + pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4; + pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU; + pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU; + + return region_origin + pos_local; +} + +void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector* positions, const LLVector3d& relative_to, F32 radius) const +{ + F32 radius_squared = radius * radius; + + if(avatar_ids != NULL) + { + avatar_ids->clear(); + } + if(positions != NULL) + { + positions->clear(); + } + // get the list of avatars from the character list first, so distances are correct + // when agent is above 1020m and other avatars are nearby + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; + LLVector3d pos_global = pVOAvatar->getPositionGlobal(); + LLUUID uuid = pVOAvatar->getID(); + if( !pVOAvatar->isDead() + && !pVOAvatar->isSelf() + && !uuid.isNull() && + dist_vec_squared(pos_global, relative_to) <= radius_squared) + { + if(positions != NULL) + { + positions->push_back(pos_global); + } + if(avatar_ids !=NULL) + { + avatar_ids->push_back(uuid); + } + } + } + // region avatars added for situations where radius is greater than RenderFarClip + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* regionp = *iter; + const LLVector3d& origin_global = regionp->getOriginGlobal(); + S32 count = regionp->mMapAvatars.count(); + for (S32 i = 0; i < count; i++) + { + LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) + { + LLUUID uuid = regionp->mMapAvatarIDs.get(i); + // if this avatar doesn't already exist in the list, add it + if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) + { + if (positions != NULL) + { + positions->push_back(pos_global); + } + avatar_ids->push_back(uuid); + } + } + } + } +} + + +LLHTTPRegistration + gHTTPRegistrationEstablishAgentCommunication( + "/message/EstablishAgentCommunication"); -- cgit v1.2.3