diff options
23 files changed, 7827 insertions, 7810 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 <iostream>
-#include "apr_base64.h"
-
-#ifdef LL_STANDALONE
-# include <zlib.h>
-#else
-# include "zlib/zlib.h" // for davep's dirty little zip functions
-#endif
-
-#if !LL_WINDOWS
-#include <netinet/in.h> // 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[] = "<llsd>";
-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<LLSDFormatter> f = NULL;
-
- switch (type)
- {
- case LLSD_BINARY:
- str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
- f = new LLSDBinaryFormatter;
- break;
-
- case LLSD_XML:
- str << "<? " << LLSD_XML_HEADER << " ?>\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<LLSDParser> 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("<? ");
- if (start != std::string::npos)
- {
- end = header.find_first_of(" ?", start);
- }
- if ((start == std::string::npos) || (end == std::string::npos))
- goto fail;
-
- header = header.substr(start, end - start);
- ws(str);
- }
- /*
- * Create the parser as appropriate
- */
- if (legacy_no_header)
- { // Create a LLSD XML parser, and parse the first chunk read above
- LLSDXMLParser* x = new LLSDXMLParser();
- x->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<U8> 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<U8> 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<U8> 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: '!'<br>
- * Boolean: 't' for true 'f' for false<br>
- * Integer: 'i' + 4 bytes network byte order<br>
- * Real: 'r' + 8 bytes IEEE double<br>
- * UUID: 'u' + 16 byte unsigned integer<br>
- * String: 's' + 4 byte integer size + string<br>
- * strings also secretly support the notation format
- * Date: 'd' + 8 byte IEEE double for seconds since epoch<br>
- * URI: 'l' + 4 byte integer size + string uri<br>
- * Binary: 'b' + 4 byte integer size + binary data<br>
- * Array: '[' + 4 byte integer size + all values + ']'<br>
- * Map: '{' + 4 byte integer size every(key + value) + '}'<br>
- * 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<U8> 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<char> 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<U8> 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<U8> 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<char> 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("<? LLSD/Binary ?>");
-
- 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 <iostream> +#include "apr_base64.h" + +#ifdef LL_STANDALONE +# include <zlib.h> +#else +# include "zlib/zlib.h" // for davep's dirty little zip functions +#endif + +#if !LL_WINDOWS +#include <netinet/in.h> // 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[] = "<llsd>"; +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<LLSDFormatter> f = NULL; + + switch (type) + { + case LLSD_BINARY: + str << "<? " << LLSD_BINARY_HEADER << " ?>\n"; + f = new LLSDBinaryFormatter; + break; + + case LLSD_XML: + str << "<? " << LLSD_XML_HEADER << " ?>\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<LLSDParser> 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("<? "); + if (start != std::string::npos) + { + end = header.find_first_of(" ?", start); + } + if ((start == std::string::npos) || (end == std::string::npos)) + goto fail; + + header = header.substr(start, end - start); + ws(str); + } + /* + * Create the parser as appropriate + */ + if (legacy_no_header) + { // Create a LLSD XML parser, and parse the first chunk read above + LLSDXMLParser* x = new LLSDXMLParser(); + x->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<U8> 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<U8> 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<U8> 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: '!'<br> + * Boolean: 't' for true 'f' for false<br> + * Integer: 'i' + 4 bytes network byte order<br> + * Real: 'r' + 8 bytes IEEE double<br> + * UUID: 'u' + 16 byte unsigned integer<br> + * String: 's' + 4 byte integer size + string<br> + * strings also secretly support the notation format + * Date: 'd' + 8 byte IEEE double for seconds since epoch<br> + * URI: 'l' + 4 byte integer size + string uri<br> + * Binary: 'b' + 4 byte integer size + binary data<br> + * Array: '[' + 4 byte integer size + all values + ']'<br> + * Map: '{' + 4 byte integer size every(key + value) + '}'<br> + * 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<U8> 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<char> 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<U8> 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<U8> 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<char> 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("<? LLSD/Binary ?>"); + + 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 <boost/bind.hpp>
-
-//---------------------------------------------------------------------------
-// LLFloaterPathfindingBasic
-//---------------------------------------------------------------------------
-
-BOOL LLFloaterPathfindingBasic::postBuild()
-{
- mStatusText = findChild<LLTextBase>("status_label");
- llassert(mStatusText != NULL);
-
- mUnfreezeLabel = findChild<LLTextBase>("unfreeze_label");
- llassert(mUnfreezeLabel != NULL);
-
- mUnfreezeButton = findChild<LLButton>("enter_unfrozen_mode");
- llassert(mUnfreezeButton != NULL);
- mUnfreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onUnfreezeClicked, this));
-
- mFreezeLabel = findChild<LLTextBase>("freeze_label");
- llassert(mFreezeLabel != NULL);
-
- mFreezeButton = findChild<LLButton>("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 <boost/bind.hpp> + +//--------------------------------------------------------------------------- +// LLFloaterPathfindingBasic +//--------------------------------------------------------------------------- + +BOOL LLFloaterPathfindingBasic::postBuild() +{ + mStatusText = findChild<LLTextBase>("status_label"); + llassert(mStatusText != NULL); + + mUnfreezeLabel = findChild<LLTextBase>("unfreeze_label"); + llassert(mUnfreezeLabel != NULL); + + mUnfreezeButton = findChild<LLButton>("enter_unfrozen_mode"); + llassert(mUnfreezeButton != NULL); + mUnfreezeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingBasic::onUnfreezeClicked, this)); + + mFreezeLabel = findChild<LLTextBase>("freeze_label"); + llassert(mFreezeLabel != NULL); + + mFreezeButton = findChild<LLButton>("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<LLScrollListCtrl>("pathfinding_characters");
- llassert(mCharactersScrollList != NULL);
- mCharactersScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onCharactersSelectionChange, this));
- mCharactersScrollList->sortByColumnIndex(0, true);
-
- mCharactersStatus = findChild<LLTextBase>("characters_status");
- llassert(mCharactersStatus != NULL);
-
- mRefreshListButton = findChild<LLButton>("refresh_characters_list");
- llassert(mRefreshListButton != NULL);
- mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onRefreshCharactersClicked, this));
-
- mSelectAllButton = findChild<LLButton>("select_all_characters");
- llassert(mSelectAllButton != NULL);
- mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectAllCharactersClicked, this));
-
- mSelectNoneButton = findChild<LLButton>("select_none_characters");
- llassert(mSelectNoneButton != NULL);
- mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectNoneCharactersClicked, this));
-
- mShowBeaconCheckBox = findChild<LLCheckBoxCtrl>("show_beacon");
- llassert(mShowBeaconCheckBox != NULL);
-
- mTakeButton = findChild<LLButton>("take_characters");
- llassert(mTakeButton != NULL)
- mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCharactersClicked, this));
-
- mTakeCopyButton = findChild<LLButton>("take_copy_characters");
- llassert(mTakeCopyButton != NULL)
- mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCopyCharactersClicked, this));
-
- mReturnButton = findChild<LLButton>("return_characters");
- llassert(mReturnButton != NULL)
- mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onReturnCharactersClicked, this));
-
- mDeleteButton = findChild<LLButton>("delete_characters");
- llassert(mDeleteButton != NULL)
- mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onDeleteCharactersClicked, this));
-
- mTeleportButton = findChild<LLButton>("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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- int numSelectedItems = selectedItems.size();
-
- std::vector<LLViewerObject *> viewerObjects;
- viewerObjects.reserve(numSelectedItems);
-
- for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- int numSelectedItems = selectedItems.size();
-
- std::vector<LLViewerObject *> viewerObjects;
- viewerObjects.reserve(numSelectedItems);
-
- for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected();
- llassert(selectedItems.size() == 1);
- if (selectedItems.size() == 1)
- {
- std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected();
- int numSelectedItems = selectedItems.size();
- uuid_vec_t selectedUUIDs;
- if (numSelectedItems > 0)
- {
- selectedUUIDs.reserve(selectedItems.size());
- for (std::vector<LLScrollListItem*>::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<LLScrollListCtrl>("pathfinding_characters"); + llassert(mCharactersScrollList != NULL); + mCharactersScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onCharactersSelectionChange, this)); + mCharactersScrollList->sortByColumnIndex(0, true); + + mCharactersStatus = findChild<LLTextBase>("characters_status"); + llassert(mCharactersStatus != NULL); + + mRefreshListButton = findChild<LLButton>("refresh_characters_list"); + llassert(mRefreshListButton != NULL); + mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onRefreshCharactersClicked, this)); + + mSelectAllButton = findChild<LLButton>("select_all_characters"); + llassert(mSelectAllButton != NULL); + mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectAllCharactersClicked, this)); + + mSelectNoneButton = findChild<LLButton>("select_none_characters"); + llassert(mSelectNoneButton != NULL); + mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onSelectNoneCharactersClicked, this)); + + mShowBeaconCheckBox = findChild<LLCheckBoxCtrl>("show_beacon"); + llassert(mShowBeaconCheckBox != NULL); + + mTakeButton = findChild<LLButton>("take_characters"); + llassert(mTakeButton != NULL) + mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCharactersClicked, this)); + + mTakeCopyButton = findChild<LLButton>("take_copy_characters"); + llassert(mTakeCopyButton != NULL) + mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onTakeCopyCharactersClicked, this)); + + mReturnButton = findChild<LLButton>("return_characters"); + llassert(mReturnButton != NULL) + mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onReturnCharactersClicked, this)); + + mDeleteButton = findChild<LLButton>("delete_characters"); + llassert(mDeleteButton != NULL) + mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onDeleteCharactersClicked, this)); + + mTeleportButton = findChild<LLButton>("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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector<LLViewerObject *> viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector<LLViewerObject *> viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected(); + llassert(selectedItems.size() == 1); + if (selectedItems.size() == 1) + { + std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mCharactersScrollList->getAllSelected(); + int numSelectedItems = selectedItems.size(); + uuid_vec_t selectedUUIDs; + if (numSelectedItems > 0) + { + selectedUUIDs.reserve(selectedItems.size()); + for (std::vector<LLScrollListItem*>::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 <string>
-#include <map>
-
-#include "llfloater.h"
-#include "llpathfindingcharacter.h"
-#include "llpathfindingcharacterlist.h"
-#include "llpathfindingmanager.h"
-#include "llselectmgr.h"
-
-#include <boost/signals2.hpp>
-
-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 <string> +#include <map> + +#include "llfloater.h" +#include "llpathfindingcharacter.h" +#include "llpathfindingcharacterlist.h" +#include "llpathfindingmanager.h" +#include "llselectmgr.h" + +#include <boost/signals2.hpp> + +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/llfloaterpathfindingconsole.cpp b/indra/newview/llfloaterpathfindingconsole.cpp index ca78042c2b..2ccba3604b 100644 --- a/indra/newview/llfloaterpathfindingconsole.cpp +++ b/indra/newview/llfloaterpathfindingconsole.cpp @@ -68,6 +68,7 @@ #define SET_SHAPE_RENDER_FLAG(_flag,_type) _flag |= (1U << _type) +#define CONTROL_NAME_RETRIEVE_NEIGHBOR "RetrieveNeighboringRegion" #define CONTROL_NAME_WALKABLE_OBJECTS "PathfindingWalkable" #define CONTROL_NAME_STATIC_OBSTACLE_OBJECTS "PathfindingObstacle" #define CONTROL_NAME_MATERIAL_VOLUMES "PathfindingMaterial" @@ -237,7 +238,7 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey) mIsNavMeshUpdating = false; initializeNavMeshZoneForCurrentRegion(); - registerNavMeshColorListeners(); + registerSavedSettingsListeners(); fillInColorsForNavMeshVisualization(); } @@ -294,7 +295,7 @@ void LLFloaterPathfindingConsole::onClose(bool pIsAppQuitting) { mNavMeshZone.disable(); } - deregisterNavMeshColorListeners(); + deregisterSavedSettingsListeners(); setDefaultInputs(); setConsoleState(kConsoleStateUnknown); @@ -512,6 +513,7 @@ LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed) mPathEventSlot(), mPathfindingToolset(NULL), mSavedToolset(NULL), + mSavedSettingRetrieveNeighborSlot(), mSavedSettingWalkableSlot(), mSavedSettingStaticObstacleSlot(), mSavedSettingMaterialVolumeSlot(), @@ -1169,8 +1171,12 @@ U32 LLFloaterPathfindingConsole::getRenderShapeFlags() return shapeRenderFlag; } -void LLFloaterPathfindingConsole::registerNavMeshColorListeners() +void LLFloaterPathfindingConsole::registerSavedSettingsListeners() { + if (!mSavedSettingRetrieveNeighborSlot.connected()) + { + mSavedSettingRetrieveNeighborSlot = gSavedSettings.getControl(CONTROL_NAME_RETRIEVE_NEIGHBOR)->getSignal()->connect(boost::bind(&LLFloaterPathfindingConsole::handleRetrieveNeighborChange, this, _1, _2)); + } if (!mSavedSettingWalkableSlot.connected()) { mSavedSettingWalkableSlot = gSavedSettings.getControl(CONTROL_NAME_WALKABLE_OBJECTS)->getSignal()->connect(boost::bind(&LLFloaterPathfindingConsole::handleNavMeshColorChange, this, _1, _2)); @@ -1225,8 +1231,12 @@ void LLFloaterPathfindingConsole::registerNavMeshColorListeners() } } -void LLFloaterPathfindingConsole::deregisterNavMeshColorListeners() +void LLFloaterPathfindingConsole::deregisterSavedSettingsListeners() { + if (mSavedSettingRetrieveNeighborSlot.connected()) + { + mSavedSettingRetrieveNeighborSlot.disconnect(); + } if (mSavedSettingWalkableSlot.connected()) { mSavedSettingWalkableSlot.disconnect(); @@ -1277,6 +1287,11 @@ void LLFloaterPathfindingConsole::deregisterNavMeshColorListeners() } } +void LLFloaterPathfindingConsole::handleRetrieveNeighborChange(LLControlVariable *pControl, const LLSD &pNewValue) +{ + initializeNavMeshZoneForCurrentRegion(); +} + void LLFloaterPathfindingConsole::handleNavMeshColorChange(LLControlVariable *pControl, const LLSD &pNewValue) { fillInColorsForNavMeshVisualization(); diff --git a/indra/newview/llfloaterpathfindingconsole.h b/indra/newview/llfloaterpathfindingconsole.h index 3fdadfafad..72acc8a749 100644 --- a/indra/newview/llfloaterpathfindingconsole.h +++ b/indra/newview/llfloaterpathfindingconsole.h @@ -151,8 +151,9 @@ private: void clearPath(); void updatePathTestStatus(); - void registerNavMeshColorListeners(); - void deregisterNavMeshColorListeners(); + void registerSavedSettingsListeners(); + void deregisterSavedSettingsListeners(); + void handleRetrieveNeighborChange(LLControlVariable *pControl, const LLSD &pNewValue); void handleNavMeshColorChange(LLControlVariable *pControl, const LLSD &pNewValue); void fillInColorsForNavMeshVisualization(); @@ -202,6 +203,7 @@ private: LLToolset *mPathfindingToolset; LLToolset *mSavedToolset; + boost::signals2::connection mSavedSettingRetrieveNeighborSlot; boost::signals2::connection mSavedSettingWalkableSlot; boost::signals2::connection mSavedSettingStaticObstacleSlot; boost::signals2::connection mSavedSettingMaterialVolumeSlot; 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 <boost/bind.hpp>
-#include <boost/signals2.hpp>
-
-#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<LLLineEditor>("filter_by_name");
- llassert(mFilterByName != NULL);
- mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
- mFilterByName->setSelectAllonFocusReceived(true);
- mFilterByName->setCommitOnFocusLost(true);
-
- mFilterByDescription = findChild<LLLineEditor>("filter_by_description");
- llassert(mFilterByDescription != NULL);
- mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
- mFilterByDescription->setSelectAllonFocusReceived(true);
- mFilterByDescription->setCommitOnFocusLost(true);
-
- mFilterByLinksetUse = findChild<LLComboBox>("filter_by_linkset_use");
- llassert(mFilterByLinksetUse != NULL);
- mFilterByLinksetUse->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
-
- mLinksetsScrollList = findChild<LLScrollListCtrl>("pathfinding_linksets");
- llassert(mLinksetsScrollList != NULL);
- mLinksetsScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onLinksetsSelectionChange, this));
- mLinksetsScrollList->sortByColumnIndex(0, true);
-
- mLinksetsStatus = findChild<LLTextBase>("linksets_status");
- llassert(mLinksetsStatus != NULL);
-
- mRefreshListButton = findChild<LLButton>("refresh_linksets_list");
- llassert(mRefreshListButton != NULL);
- mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onRefreshLinksetsClicked, this));
-
- mSelectAllButton = findChild<LLButton>("select_all_linksets");
- llassert(mSelectAllButton != NULL);
- mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectAllLinksetsClicked, this));
-
- mSelectNoneButton = findChild<LLButton>("select_none_linksets");
- llassert(mSelectNoneButton != NULL);
- mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectNoneLinksetsClicked, this));
-
- mShowBeaconCheckBox = findChild<LLCheckBoxCtrl>("show_beacon");
- llassert(mShowBeaconCheckBox != NULL);
-
- mTakeButton = findChild<LLButton>("take_linksets");
- llassert(mTakeButton != NULL);
- mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeClicked, this));
-
- mTakeCopyButton = findChild<LLButton>("take_copy_linksets");
- llassert(mTakeCopyButton != NULL);
- mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeCopyClicked, this));
-
- mReturnButton = findChild<LLButton>("return_linksets");
- llassert(mReturnButton != NULL);
- mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onReturnClicked, this));
-
- mDeleteButton = findChild<LLButton>("delete_linksets");
- llassert(mDeleteButton != NULL);
- mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onDeleteClicked, this));
-
- mTeleportButton = findChild<LLButton>("teleport_me_to_linkset");
- llassert(mTeleportButton != NULL);
- mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTeleportClicked, this));
-
- mEditLinksetUse = findChild<LLComboBox>("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<LLTextBase>("walkability_coefficients_label");
- llassert(mLabelWalkabilityCoefficients != NULL);
-
- mLabelEditA = findChild<LLTextBase>("edit_a_label");
- llassert(mLabelEditA != NULL);
-
- mEditA = findChild<LLLineEditor>("edit_a_value");
- llassert(mEditA != NULL);
- mEditA->setPrevalidate(LLTextValidate::validateNonNegativeS32);
- mEditA->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1));
-
- mLabelEditB = findChild<LLTextBase>("edit_b_label");
- llassert(mLabelEditB != NULL);
-
- mEditB = findChild<LLLineEditor>("edit_b_value");
- llassert(mEditB != NULL);
- mEditB->setPrevalidate(LLTextValidate::validateNonNegativeS32);
- mEditB->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1));
-
- mLabelEditC = findChild<LLTextBase>("edit_c_label");
- llassert(mLabelEditC != NULL);
-
- mEditC = findChild<LLLineEditor>("edit_c_value");
- llassert(mEditC != NULL);
- mEditC->setPrevalidate(LLTextValidate::validateNonNegativeS32);
- mEditC->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1));
-
- mLabelEditD = findChild<LLTextBase>("edit_d_label");
- llassert(mLabelEditD != NULL);
-
- mEditD = findChild<LLLineEditor>("edit_d_value");
- llassert(mEditD != NULL);
- mEditD->setPrevalidate(LLTextValidate::validateNonNegativeS32);
- mEditD->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1));
-
- mApplyEditsButton = findChild<LLButton>("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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- int numSelectedItems = selectedItems.size();
-
- std::vector<LLViewerObject *> viewerObjects;
- viewerObjects.reserve(numSelectedItems);
-
- for (std::vector<LLScrollListItem*>::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<LLScrollListItem *> selectedItems = mLinksetsScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- int numSelectedItems = selectedItems.size();
-
- std::vector<LLViewerObject *>viewerObjects;
- viewerObjects.reserve(numSelectedItems);
-
- for (std::vector<LLScrollListItem *>::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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
- llassert(selectedItems.size() == 1);
- if (selectedItems.size() == 1)
- {
- std::vector<LLScrollListItem*>::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<LLLineEditor *>(pUICtrl);
- llassert(pLineEditor != NULL);
-
- const std::string &valueString = pLineEditor->getText();
- S32 value = static_cast<S32>(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<LLScrollListItem*> 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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
- int numSelectedItems = selectedItems.size();
- uuid_vec_t selectedUUIDs;
- if (numSelectedItems > 0)
- {
- selectedUUIDs.reserve(selectedItems.size());
- for (std::vector<LLScrollListItem*>::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<LLSD::Real>(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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
- if (!selectedItems.empty())
- {
- for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> 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<S32>(atoi(aString.c_str()));
- S32 bValue = static_cast<S32>(atoi(bString.c_str()));
- S32 cValue = static_cast<S32>(atoi(cString.c_str()));
- S32 dValue = static_cast<S32>(atoi(dString.c_str()));
-
- LLPathfindingLinksetListPtr editListPtr(new LLPathfindingLinksetList());
- for (std::vector<LLScrollListItem*>::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<std::string, LLPathfindingLinksetPtr>(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 <boost/bind.hpp> +#include <boost/signals2.hpp> + +#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<LLLineEditor>("filter_by_name"); + llassert(mFilterByName != NULL); + mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByName->setSelectAllonFocusReceived(true); + mFilterByName->setCommitOnFocusLost(true); + + mFilterByDescription = findChild<LLLineEditor>("filter_by_description"); + llassert(mFilterByDescription != NULL); + mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByDescription->setSelectAllonFocusReceived(true); + mFilterByDescription->setCommitOnFocusLost(true); + + mFilterByLinksetUse = findChild<LLComboBox>("filter_by_linkset_use"); + llassert(mFilterByLinksetUse != NULL); + mFilterByLinksetUse->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + + mLinksetsScrollList = findChild<LLScrollListCtrl>("pathfinding_linksets"); + llassert(mLinksetsScrollList != NULL); + mLinksetsScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onLinksetsSelectionChange, this)); + mLinksetsScrollList->sortByColumnIndex(0, true); + + mLinksetsStatus = findChild<LLTextBase>("linksets_status"); + llassert(mLinksetsStatus != NULL); + + mRefreshListButton = findChild<LLButton>("refresh_linksets_list"); + llassert(mRefreshListButton != NULL); + mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onRefreshLinksetsClicked, this)); + + mSelectAllButton = findChild<LLButton>("select_all_linksets"); + llassert(mSelectAllButton != NULL); + mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectAllLinksetsClicked, this)); + + mSelectNoneButton = findChild<LLButton>("select_none_linksets"); + llassert(mSelectNoneButton != NULL); + mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onSelectNoneLinksetsClicked, this)); + + mShowBeaconCheckBox = findChild<LLCheckBoxCtrl>("show_beacon"); + llassert(mShowBeaconCheckBox != NULL); + + mTakeButton = findChild<LLButton>("take_linksets"); + llassert(mTakeButton != NULL); + mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeClicked, this)); + + mTakeCopyButton = findChild<LLButton>("take_copy_linksets"); + llassert(mTakeCopyButton != NULL); + mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTakeCopyClicked, this)); + + mReturnButton = findChild<LLButton>("return_linksets"); + llassert(mReturnButton != NULL); + mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onReturnClicked, this)); + + mDeleteButton = findChild<LLButton>("delete_linksets"); + llassert(mDeleteButton != NULL); + mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onDeleteClicked, this)); + + mTeleportButton = findChild<LLButton>("teleport_me_to_linkset"); + llassert(mTeleportButton != NULL); + mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onTeleportClicked, this)); + + mEditLinksetUse = findChild<LLComboBox>("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<LLTextBase>("walkability_coefficients_label"); + llassert(mLabelWalkabilityCoefficients != NULL); + + mLabelEditA = findChild<LLTextBase>("edit_a_label"); + llassert(mLabelEditA != NULL); + + mEditA = findChild<LLLineEditor>("edit_a_value"); + llassert(mEditA != NULL); + mEditA->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditA->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mLabelEditB = findChild<LLTextBase>("edit_b_label"); + llassert(mLabelEditB != NULL); + + mEditB = findChild<LLLineEditor>("edit_b_value"); + llassert(mEditB != NULL); + mEditB->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditB->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mLabelEditC = findChild<LLTextBase>("edit_c_label"); + llassert(mLabelEditC != NULL); + + mEditC = findChild<LLLineEditor>("edit_c_value"); + llassert(mEditC != NULL); + mEditC->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditC->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mLabelEditD = findChild<LLTextBase>("edit_d_label"); + llassert(mLabelEditD != NULL); + + mEditD = findChild<LLLineEditor>("edit_d_value"); + llassert(mEditD != NULL); + mEditD->setPrevalidate(LLTextValidate::validateNonNegativeS32); + mEditD->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered, this, _1)); + + mApplyEditsButton = findChild<LLButton>("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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector<LLViewerObject *> viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector<LLScrollListItem*>::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<LLScrollListItem *> selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + int numSelectedItems = selectedItems.size(); + + std::vector<LLViewerObject *>viewerObjects; + viewerObjects.reserve(numSelectedItems); + + for (std::vector<LLScrollListItem *>::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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected(); + llassert(selectedItems.size() == 1); + if (selectedItems.size() == 1) + { + std::vector<LLScrollListItem*>::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<LLLineEditor *>(pUICtrl); + llassert(pLineEditor != NULL); + + const std::string &valueString = pLineEditor->getText(); + S32 value = static_cast<S32>(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<LLScrollListItem*> 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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected(); + int numSelectedItems = selectedItems.size(); + uuid_vec_t selectedUUIDs; + if (numSelectedItems > 0) + { + selectedUUIDs.reserve(selectedItems.size()); + for (std::vector<LLScrollListItem*>::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<LLSD::Real>(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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected(); + if (!selectedItems.empty()) + { + for (std::vector<LLScrollListItem*>::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<LLScrollListItem*> 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<S32>(atoi(aString.c_str())); + S32 bValue = static_cast<S32>(atoi(bString.c_str())); + S32 cValue = static_cast<S32>(atoi(cString.c_str())); + S32 dValue = static_cast<S32>(atoi(dString.c_str())); + + LLPathfindingLinksetListPtr editListPtr(new LLPathfindingLinksetList()); + for (std::vector<LLScrollListItem*>::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<std::string, LLPathfindingLinksetPtr>(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 <boost/signals2.hpp>
-
-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 <boost/signals2.hpp> + +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<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(FALSE);
- }
+ if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) + { + sendIsFlexible(); + } + else + { + getChild<LLUICtrl>("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 <boost/shared_ptr.hpp>
-
-class LLSD;
-class LLPathfindingCharacter;
-
-typedef boost::shared_ptr<LLPathfindingCharacter> 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 <boost/shared_ptr.hpp> + +class LLSD; +class LLPathfindingCharacter; + +typedef boost::shared_ptr<LLPathfindingCharacter> 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 <string>
-#include <map>
-
-#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<std::string, LLPathfindingCharacterPtr>(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 <string> +#include <map> + +#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<std::string, LLPathfindingCharacterPtr>(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 <string>
-#include <map>
-#include "llpathfindingcharacter.h"
-
-#include <boost/shared_ptr.hpp>
-
-class LLSD;
-class LLPathfindingCharacterList;
-
-typedef boost::shared_ptr<LLPathfindingCharacterList> LLPathfindingCharacterListPtr;
-typedef std::map<std::string, LLPathfindingCharacterPtr> 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 <string> +#include <map> +#include "llpathfindingcharacter.h" + +#include <boost/shared_ptr.hpp> + +class LLSD; +class LLPathfindingCharacterList; + +typedef boost::shared_ptr<LLPathfindingCharacterList> LLPathfindingCharacterListPtr; +typedef std::map<std::string, LLPathfindingCharacterPtr> 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<bool>(isPhantom(pLinksetUse));
- }
-
-#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS
- itemData[DEPRECATED_LINKSET_PERMANENT_FIELD] = static_cast<bool>(isPermanent(pLinksetUse));
- itemData[DEPRECATED_LINKSET_WALKABLE_FIELD] = static_cast<bool>(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<S32>(LINKSET_CATEGORY_VALUE_IGNORE);
- break;
- case kNavMeshGenerationInclude :
- llsd = static_cast<S32>(LINKSET_CATEGORY_VALUE_INCLUDE);
- break;
- case kNavMeshGenerationExclude :
- llsd = static_cast<S32>(LINKSET_CATEGORY_VALUE_EXCLUDE);
- break;
- default :
- llsd = static_cast<S32>(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<bool>(isPhantom(pLinksetUse)); + } + +#ifdef DEPRECATED_NAVMESH_PERMANENT_WALKABLE_FLAGS + itemData[DEPRECATED_LINKSET_PERMANENT_FIELD] = static_cast<bool>(isPermanent(pLinksetUse)); + itemData[DEPRECATED_LINKSET_WALKABLE_FIELD] = static_cast<bool>(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<S32>(LINKSET_CATEGORY_VALUE_IGNORE); + break; + case kNavMeshGenerationInclude : + llsd = static_cast<S32>(LINKSET_CATEGORY_VALUE_INCLUDE); + break; + case kNavMeshGenerationExclude : + llsd = static_cast<S32>(LINKSET_CATEGORY_VALUE_EXCLUDE); + break; + default : + llsd = static_cast<S32>(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 <boost/shared_ptr.hpp>
-
-class LLSD;
-class LLPathfindingLinkset;
-
-typedef boost::shared_ptr<LLPathfindingLinkset> 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 <boost/shared_ptr.hpp> + +class LLSD; +class LLPathfindingLinkset; + +typedef boost::shared_ptr<LLPathfindingLinkset> 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 <string>
-#include <map>
-
-#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<std::string, LLPathfindingLinksetPtr>(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<std::string, LLPathfindingLinksetPtr>(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 <string> +#include <map> + +#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<std::string, LLPathfindingLinksetPtr>(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<std::string, LLPathfindingLinksetPtr>(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 <string>
-#include <map>
-#include "llpathfindinglinkset.h"
-
-#include <boost/shared_ptr.hpp>
-
-class LLSD;
-class LLPathfindingLinksetList;
-
-typedef boost::shared_ptr<LLPathfindingLinksetList> LLPathfindingLinksetListPtr;
-typedef std::map<std::string, LLPathfindingLinksetPtr> 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 <string> +#include <map> +#include "llpathfindinglinkset.h" + +#include <boost/shared_ptr.hpp> + +class LLSD; +class LLPathfindingLinksetList; + +typedef boost::shared_ptr<LLPathfindingLinksetList> LLPathfindingLinksetListPtr; +typedef std::map<std::string, LLPathfindingLinksetPtr> 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 <string>
-
-#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<U32>(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 <string> + +#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<U32>(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 <string>
-
-// 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 <string> + +// 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 <boost/function.hpp>
-#include <boost/signals2.hpp>
-
-#define PATH_TOOL_NAME "PathfindingPathTool"
-
-LLPathfindingPathTool::LLPathfindingPathTool()
- : LLTool(PATH_TOOL_NAME),
- LLSingleton<LLPathfindingPathTool>(),
- 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 <boost/function.hpp> +#include <boost/signals2.hpp> + +#define PATH_TOOL_NAME "PathfindingPathTool" + +LLPathfindingPathTool::LLPathfindingPathTool() + : LLTool(PATH_TOOL_NAME), + LLSingleton<LLPathfindingPathTool>(), + 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 <boost/function.hpp>
-#include <boost/signals2.hpp>
-
-class LLPathfindingPathTool : public LLTool, public LLSingleton<LLPathfindingPathTool>
-{
-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<void (void)> path_event_callback_t;
- typedef boost::signals2::signal<void (void)> 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 <boost/function.hpp> +#include <boost/signals2.hpp> + +class LLPathfindingPathTool : public LLTool, public LLSingleton<LLPathfindingPathTool> +{ +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<void (void)> path_event_callback_t; + typedef boost::signals2::signal<void (void)> 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 <deque>
-#include <queue>
-#include <map>
-#include <cstring>
-
-
-//
-// 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<LLImageRaw> 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<LLVOWater*>::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<LLVector3d>* 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<LLCharacter*>::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<LLEstablishAgentCommunication>
- 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 <deque> +#include <queue> +#include <map> +#include <cstring> + + +// +// 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<LLImageRaw> 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<LLVOWater*>::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<LLVector3d>* 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<LLCharacter*>::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<LLEstablishAgentCommunication> + gHTTPRegistrationEstablishAgentCommunication( + "/message/EstablishAgentCommunication"); |