Merge
commit
9f2302bdff
|
|
@ -1,6 +1,5 @@
|
|||
syntax: glob
|
||||
|
||||
|
||||
# WinMerge temp files
|
||||
*.bak
|
||||
# Compiled python bytecode
|
||||
|
|
|
|||
1
.hgtags
1
.hgtags
|
|
@ -503,3 +503,4 @@ afd8d4756e8eda3c8f760625d1c17a2ad40ad6c8 3.7.27-release
|
|||
566874eb5ab26c003ef7fb0e22ce40c5fa0013f4 3.7.28-release
|
||||
d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release
|
||||
67edc442c80b8d2fadd2a6c4a7184b469906cdbf 3.7.30-release
|
||||
797ed69e6134ef48bb922577ab2540fb2d964668 3.8.0-release
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ additional_packages = ""
|
|||
# the viewer_channel_suffix is prefixed by a blank and then appended to the viewer_channel
|
||||
# for the package in a setting that overrides the compiled-in value
|
||||
################################################################
|
||||
additional_packages = "EDU"
|
||||
|
||||
# The EDU package allows us to create a separate release channel whose expirations
|
||||
# are synchronized as much as possible with the academic year
|
||||
EDU_sourceid = ""
|
||||
EDU_viewer_channel_suffix = "edu"
|
||||
|
||||
# Notifications - to configure email notices, add a setting like this:
|
||||
# <username>_<reponame>.email = <email-address>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
#include "llsdutil_math.h"
|
||||
#include "message.h"
|
||||
#include "u64.h"
|
||||
#include "llregionflags.h"
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
|
||||
static const F32 SOME_BIG_NUMBER = 1000.0f;
|
||||
static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
|
||||
|
|
@ -627,8 +629,8 @@ void LLParcel::unpackMessage(LLMessageSystem* msg)
|
|||
void LLParcel::packAccessEntries(LLMessageSystem* msg,
|
||||
const std::map<LLUUID,LLAccessEntry>& list)
|
||||
{
|
||||
access_map_const_iterator cit = list.begin();
|
||||
access_map_const_iterator end = list.end();
|
||||
LLAccessEntry::map::const_iterator cit = list.begin();
|
||||
LLAccessEntry::map::const_iterator end = list.end();
|
||||
|
||||
if (cit == end)
|
||||
{
|
||||
|
|
@ -679,9 +681,28 @@ void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
|
|||
}
|
||||
|
||||
|
||||
void LLParcel::unpackExperienceEntries( LLMessageSystem* msg, U32 type )
|
||||
{
|
||||
LLUUID id;
|
||||
|
||||
S32 i;
|
||||
S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
|
||||
|
||||
if (id.notNull())
|
||||
{
|
||||
mExperienceKeys[id]=type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLParcel::expirePasses(S32 now)
|
||||
{
|
||||
access_map_iterator itor = mAccessList.begin();
|
||||
LLAccessEntry::map::iterator itor = mAccessList.begin();
|
||||
while (itor != mAccessList.end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
|
|
@ -771,7 +792,7 @@ BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
|
|||
// Can't add owner to these lists
|
||||
return FALSE;
|
||||
}
|
||||
access_map_iterator itor = mAccessList.begin();
|
||||
LLAccessEntry::map::iterator itor = mAccessList.begin();
|
||||
while (itor != mAccessList.end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
|
|
@ -814,7 +835,7 @@ BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
access_map_iterator itor = mBanList.begin();
|
||||
LLAccessEntry::map::iterator itor = mBanList.begin();
|
||||
while (itor != mBanList.end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
|
|
@ -848,7 +869,7 @@ BOOL remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
|
|||
const LLUUID& agent_id)
|
||||
{
|
||||
BOOL removed = FALSE;
|
||||
access_map_iterator itor = list->begin();
|
||||
LLAccessEntry::map::iterator itor = list->begin();
|
||||
while (itor != list->end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
|
|
@ -1191,3 +1212,58 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s)
|
|||
// is a distinct option from "None" and "Other"
|
||||
return LLParcel::C_ANY;
|
||||
}
|
||||
|
||||
LLAccessEntry::map LLParcel::getExperienceKeysByType( U32 type ) const
|
||||
{
|
||||
LLAccessEntry::map access;
|
||||
LLAccessEntry entry;
|
||||
xp_type_map_t::const_iterator it = mExperienceKeys.begin();
|
||||
for(/**/; it != mExperienceKeys.end(); ++it)
|
||||
{
|
||||
if(it->second == type)
|
||||
{
|
||||
entry.mID = it->first;
|
||||
access[entry.mID] = entry;
|
||||
}
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
void LLParcel::clearExperienceKeysByType( U32 type )
|
||||
{
|
||||
xp_type_map_t::iterator it = mExperienceKeys.begin();
|
||||
while(it != mExperienceKeys.end())
|
||||
{
|
||||
if(it->second == type)
|
||||
{
|
||||
mExperienceKeys.erase(it++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLParcel::setExperienceKeyType( const LLUUID& experience_key, U32 type )
|
||||
{
|
||||
if(type == EXPERIENCE_KEY_TYPE_NONE)
|
||||
{
|
||||
mExperienceKeys.erase(experience_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(countExperienceKeyType(type) < PARCEL_MAX_EXPERIENCE_LIST)
|
||||
{
|
||||
mExperienceKeys[experience_key] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLParcel::countExperienceKeyType( U32 type )
|
||||
{
|
||||
return std::count_if(
|
||||
boost::begin(mExperienceKeys | boost::adaptors::map_values),
|
||||
boost::end(mExperienceKeys | boost::adaptors::map_values),
|
||||
std::bind2nd(std::equal_to<U32>(), type));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ const S32 PARCEL_MAX_ACCESS_LIST = 300;
|
|||
//for access/ban lists.
|
||||
const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
|
||||
|
||||
// Maximum number of experiences
|
||||
const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
|
||||
|
||||
// Weekly charge for listing a parcel in the directory
|
||||
const S32 PARCEL_DIRECTORY_FEE = 30;
|
||||
|
||||
|
|
@ -130,9 +133,11 @@ class LLSD;
|
|||
class LLAccessEntry
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::map<LLUUID,LLAccessEntry> map;
|
||||
|
||||
LLAccessEntry()
|
||||
: mID(),
|
||||
mTime(0),
|
||||
: mTime(0),
|
||||
mFlags(0)
|
||||
{}
|
||||
|
||||
|
|
@ -141,8 +146,6 @@ public:
|
|||
U32 mFlags; // Not used - currently should always be zero
|
||||
};
|
||||
|
||||
typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
|
||||
typedef std::map<LLUUID,LLAccessEntry>::const_iterator access_map_const_iterator;
|
||||
|
||||
class LLParcel
|
||||
{
|
||||
|
|
@ -320,6 +323,9 @@ public:
|
|||
void unpackAccessEntries(LLMessageSystem* msg,
|
||||
std::map<LLUUID,LLAccessEntry>* list);
|
||||
|
||||
void unpackExperienceEntries(LLMessageSystem* msg, U32 type);
|
||||
|
||||
|
||||
void setAABBMin(const LLVector3& min) { mAABBMin = min; }
|
||||
void setAABBMax(const LLVector3& max) { mAABBMax = max; }
|
||||
|
||||
|
|
@ -665,6 +671,17 @@ public:
|
|||
std::map<LLUUID,LLAccessEntry> mTempBanList;
|
||||
std::map<LLUUID,LLAccessEntry> mTempAccessList;
|
||||
|
||||
typedef std::map<LLUUID, U32> xp_type_map_t;
|
||||
|
||||
void setExperienceKeyType(const LLUUID& experience_key, U32 type);
|
||||
U32 countExperienceKeyType(U32 type);
|
||||
U32 getExperienceKeyType(const LLUUID& experience_key)const;
|
||||
LLAccessEntry::map getExperienceKeysByType(U32 type)const;
|
||||
void clearExperienceKeysByType(U32 type);
|
||||
|
||||
private:
|
||||
xp_type_map_t mExperienceKeys;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -90,8 +90,10 @@ const U32 PF_DEFAULT = PF_ALLOW_FLY
|
|||
| PF_USE_ESTATE_VOICE_CHAN;
|
||||
|
||||
// Access list flags
|
||||
const U32 AL_ACCESS = (1 << 0);
|
||||
const U32 AL_BAN = (1 << 1);
|
||||
const U32 AL_ACCESS = (1 << 0);
|
||||
const U32 AL_BAN = (1 << 1);
|
||||
const U32 AL_ALLOW_EXPERIENCE = (1 << 3);
|
||||
const U32 AL_BLOCK_EXPERIENCE = (1 << 4);
|
||||
//const U32 AL_RENTER = (1 << 2);
|
||||
|
||||
// Block access return values. BA_ALLOWED is the only success case
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ set(llmessage_SOURCE_FILES
|
|||
llcurl.cpp
|
||||
lldatapacker.cpp
|
||||
lldispatcher.cpp
|
||||
llexperiencecache.cpp
|
||||
llfiltersd2xmlrpc.cpp
|
||||
llhost.cpp
|
||||
llhttpassetstorage.cpp
|
||||
|
|
@ -134,6 +135,7 @@ set(llmessage_HEADER_FILES
|
|||
lldbstrings.h
|
||||
lldispatcher.h
|
||||
lleventflags.h
|
||||
llexperiencecache.h
|
||||
llextendedstatus.h
|
||||
llfiltersd2xmlrpc.h
|
||||
llfollowcamparams.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,641 @@
|
|||
/**
|
||||
* @file llexperiencecache.cpp
|
||||
* @brief llexperiencecache and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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 "llexperiencecache.h"
|
||||
|
||||
#include "llavatarname.h"
|
||||
#include "llframetimer.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llsdserialize.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include "boost/tokenizer.hpp"
|
||||
|
||||
|
||||
namespace LLExperienceCache
|
||||
{
|
||||
|
||||
typedef std::map<LLUUID, LLUUID> KeyMap;
|
||||
KeyMap privateToPublicKeyMap;
|
||||
|
||||
void mapKeys(const LLSD& legacyKeys);
|
||||
|
||||
std::string sLookupURL;
|
||||
|
||||
typedef std::map<LLUUID, std::string> ask_queue_t;
|
||||
ask_queue_t sAskQueue;
|
||||
|
||||
typedef std::map<LLUUID, F64> pending_queue_t;
|
||||
pending_queue_t sPendingQueue;
|
||||
|
||||
cache_t sCache;
|
||||
int sMaximumLookups = 10;
|
||||
|
||||
LLFrameTimer sRequestTimer;
|
||||
|
||||
// Periodically clean out expired entries from the cache
|
||||
LLFrameTimer sEraseExpiredTimer;
|
||||
|
||||
// May have multiple callbacks for a single ID, which are
|
||||
// represented as multiple slots bound to the signal.
|
||||
// Avoid copying signals via pointers.
|
||||
typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
|
||||
signal_map_t sSignalMap;
|
||||
|
||||
|
||||
|
||||
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
|
||||
void eraseExpired();
|
||||
|
||||
void processExperience( const LLUUID& public_key, const LLSD& experience )
|
||||
{
|
||||
sCache[public_key]=experience;
|
||||
LLSD & row = sCache[public_key];
|
||||
|
||||
if(row.has(EXPIRES))
|
||||
{
|
||||
row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds();
|
||||
}
|
||||
|
||||
if(row.has(EXPERIENCE_ID))
|
||||
{
|
||||
sPendingQueue.erase(row[EXPERIENCE_ID].asUUID());
|
||||
}
|
||||
|
||||
//signal
|
||||
signal_map_t::iterator sig_it = sSignalMap.find(public_key);
|
||||
if (sig_it != sSignalMap.end())
|
||||
{
|
||||
callback_signal_t* signal = sig_it->second;
|
||||
(*signal)(experience);
|
||||
|
||||
sSignalMap.erase(public_key);
|
||||
|
||||
delete signal;
|
||||
}
|
||||
}
|
||||
|
||||
void initClass( )
|
||||
{
|
||||
}
|
||||
|
||||
const cache_t& getCached()
|
||||
{
|
||||
return sCache;
|
||||
}
|
||||
|
||||
void setMaximumLookups( int maximumLookups)
|
||||
{
|
||||
sMaximumLookups = maximumLookups;
|
||||
}
|
||||
|
||||
void bootstrap(const LLSD& legacyKeys, int initialExpiration)
|
||||
{
|
||||
mapKeys(legacyKeys);
|
||||
LLSD::array_const_iterator it = legacyKeys.beginArray();
|
||||
for(/**/; it != legacyKeys.endArray(); ++it)
|
||||
{
|
||||
LLSD experience = *it;
|
||||
if(experience.has(EXPERIENCE_ID))
|
||||
{
|
||||
if(!experience.has(EXPIRES))
|
||||
{
|
||||
experience[EXPIRES] = initialExpiration;
|
||||
}
|
||||
processExperience(experience[EXPERIENCE_ID].asUUID(), experience);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ExperienceCache")
|
||||
<< "Skipping bootstrap entry which is missing " << EXPERIENCE_ID
|
||||
<< LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool expirationFromCacheControl(LLSD headers, F64 *expires)
|
||||
{
|
||||
// Allow the header to override the default
|
||||
LLSD cache_control_header = headers["cache-control"];
|
||||
if (cache_control_header.isDefined())
|
||||
{
|
||||
S32 max_age = 0;
|
||||
std::string cache_control = cache_control_header.asString();
|
||||
if (max_age_from_cache_control(cache_control, &max_age))
|
||||
{
|
||||
LL_WARNS("ExperienceCache")
|
||||
<< "got EXPIRES from headers, max_age " << max_age
|
||||
<< LL_ENDL;
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
*expires = now + (F64)max_age;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static const std::string MAX_AGE("max-age");
|
||||
static const boost::char_separator<char> EQUALS_SEPARATOR("=");
|
||||
static const boost::char_separator<char> COMMA_SEPARATOR(",");
|
||||
|
||||
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age)
|
||||
{
|
||||
// Split the string on "," to get a list of directives
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer directives(cache_control, COMMA_SEPARATOR);
|
||||
|
||||
tokenizer::iterator token_it = directives.begin();
|
||||
for ( ; token_it != directives.end(); ++token_it)
|
||||
{
|
||||
// Tokens may have leading or trailing whitespace
|
||||
std::string token = *token_it;
|
||||
LLStringUtil::trim(token);
|
||||
|
||||
if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
|
||||
{
|
||||
// ...this token starts with max-age, so let's chop it up by "="
|
||||
tokenizer subtokens(token, EQUALS_SEPARATOR);
|
||||
tokenizer::iterator subtoken_it = subtokens.begin();
|
||||
|
||||
// Must have a token
|
||||
if (subtoken_it == subtokens.end()) return false;
|
||||
std::string subtoken = *subtoken_it;
|
||||
|
||||
// Must exactly equal "max-age"
|
||||
LLStringUtil::trim(subtoken);
|
||||
if (subtoken != MAX_AGE) return false;
|
||||
|
||||
// Must have another token
|
||||
++subtoken_it;
|
||||
if (subtoken_it == subtokens.end()) return false;
|
||||
subtoken = *subtoken_it;
|
||||
|
||||
// Must be a valid integer
|
||||
// *NOTE: atoi() returns 0 for invalid values, so we have to
|
||||
// check the string first.
|
||||
// *TODO: Do servers ever send "0000" for zero? We don't handle it
|
||||
LLStringUtil::trim(subtoken);
|
||||
if (subtoken == "0")
|
||||
{
|
||||
*max_age = 0;
|
||||
return true;
|
||||
}
|
||||
S32 val = atoi( subtoken.c_str() );
|
||||
if (val > 0 && val < S32_MAX)
|
||||
{
|
||||
*max_age = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void importFile(std::istream& istr)
|
||||
{
|
||||
LLSD data;
|
||||
S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
|
||||
if(parse_count < 1) return;
|
||||
|
||||
LLSD experiences = data["experiences"];
|
||||
|
||||
LLUUID public_key;
|
||||
LLSD::map_const_iterator it = experiences.beginMap();
|
||||
for(; it != experiences.endMap() ; ++it)
|
||||
{
|
||||
public_key.set(it->first);
|
||||
sCache[public_key]=it->second;
|
||||
}
|
||||
|
||||
LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL;
|
||||
}
|
||||
|
||||
void exportFile(std::ostream& ostr)
|
||||
{
|
||||
LLSD experiences;
|
||||
|
||||
cache_t::const_iterator it =sCache.begin();
|
||||
for( ; it != sCache.end() ; ++it)
|
||||
{
|
||||
if(!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() ||
|
||||
it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID))
|
||||
continue;
|
||||
|
||||
experiences[it->first.asString()] = it->second;
|
||||
}
|
||||
|
||||
LLSD data;
|
||||
data["experiences"] = experiences;
|
||||
|
||||
LLSDSerialize::toPrettyXML(data, ostr);
|
||||
}
|
||||
|
||||
class LLExperienceResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
LLExperienceResponder(const ask_queue_t& keys)
|
||||
:mKeys(keys)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*virtual*/ void httpCompleted()
|
||||
{
|
||||
LLSD experiences = getContent()["experience_keys"];
|
||||
LLSD::array_const_iterator it = experiences.beginArray();
|
||||
for( /**/ ; it != experiences.endArray(); ++it)
|
||||
{
|
||||
const LLSD& row = *it;
|
||||
LLUUID public_key = row[EXPERIENCE_ID].asUUID();
|
||||
|
||||
|
||||
LL_DEBUGS("ExperienceCache") << "Received result for " << public_key
|
||||
<< " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ;
|
||||
|
||||
processExperience(public_key, row);
|
||||
}
|
||||
|
||||
LLSD error_ids = getContent()["error_ids"];
|
||||
LLSD::array_const_iterator errIt = error_ids.beginArray();
|
||||
for( /**/ ; errIt != error_ids.endArray() ; ++errIt )
|
||||
{
|
||||
LLUUID id = errIt->asUUID();
|
||||
LLSD exp;
|
||||
exp[EXPIRES]=DEFAULT_EXPIRATION;
|
||||
exp[EXPERIENCE_ID] = id;
|
||||
exp[PROPERTIES]=PROPERTY_INVALID;
|
||||
exp[MISSING]=true;
|
||||
exp[QUOTA] = DEFAULT_QUOTA;
|
||||
|
||||
processExperience(id, exp);
|
||||
LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ;
|
||||
}
|
||||
|
||||
LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL;
|
||||
}
|
||||
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Request failed "<<getStatus()<<" "<<getReason()<< LL_ENDL;
|
||||
// We're going to construct a dummy record and cache it for a while,
|
||||
// either briefly for a 503 Service Unavailable, or longer for other
|
||||
// errors.
|
||||
F64 retry_timestamp = errorRetryTimestamp(getStatus());
|
||||
|
||||
|
||||
// Add dummy records for all agent IDs in this request
|
||||
ask_queue_t::const_iterator it = mKeys.begin();
|
||||
for ( ; it != mKeys.end(); ++it)
|
||||
{
|
||||
|
||||
LLSD exp = get(it->first);
|
||||
//leave the properties alone if we already have a cache entry for this xp
|
||||
if(exp.isUndefined())
|
||||
{
|
||||
exp[PROPERTIES]=PROPERTY_INVALID;
|
||||
}
|
||||
exp[EXPIRES]=retry_timestamp;
|
||||
exp[EXPERIENCE_ID] = it->first;
|
||||
exp["key_type"] = it->second;
|
||||
exp["uuid"] = it->first;
|
||||
exp["error"] = (LLSD::Integer)getStatus();
|
||||
exp[QUOTA] = DEFAULT_QUOTA;
|
||||
|
||||
LLExperienceCache::processExperience(it->first, exp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Return time to retry a request that generated an error, based on
|
||||
// error type and headers. Return value is seconds-since-epoch.
|
||||
F64 errorRetryTimestamp(S32 status)
|
||||
{
|
||||
|
||||
// Retry-After takes priority
|
||||
LLSD retry_after = getResponseHeaders()["retry-after"];
|
||||
if (retry_after.isDefined())
|
||||
{
|
||||
// We only support the delta-seconds type
|
||||
S32 delta_seconds = retry_after.asInteger();
|
||||
if (delta_seconds > 0)
|
||||
{
|
||||
// ...valid delta-seconds
|
||||
return F64(delta_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
// If no Retry-After, look for Cache-Control max-age
|
||||
F64 expires = 0.0;
|
||||
if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires))
|
||||
{
|
||||
return expires;
|
||||
}
|
||||
|
||||
// No information in header, make a guess
|
||||
if (status == 503)
|
||||
{
|
||||
// ...service unavailable, retry soon
|
||||
const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
|
||||
return SERVICE_UNAVAILABLE_DELAY;
|
||||
}
|
||||
else if (status == 499)
|
||||
{
|
||||
// ...we were probably too busy, retry quickly
|
||||
const F64 BUSY_DELAY = 10.0; // 10 seconds
|
||||
return BUSY_DELAY;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...other unexpected error
|
||||
const F64 DEFAULT_DELAY = 3600.0; // 1 hour
|
||||
return DEFAULT_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ask_queue_t mKeys;
|
||||
};
|
||||
|
||||
void requestExperiences()
|
||||
{
|
||||
if(sAskQueue.empty() || sLookupURL.empty())
|
||||
return;
|
||||
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
|
||||
const U32 EXP_URL_SEND_THRESHOLD = 3000;
|
||||
const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH;
|
||||
|
||||
std::ostringstream ostr;
|
||||
|
||||
ask_queue_t keys;
|
||||
|
||||
ostr << sLookupURL << "?page_size=" << PAGE_SIZE;
|
||||
|
||||
|
||||
int request_count = 0;
|
||||
while(!sAskQueue.empty() && request_count < sMaximumLookups)
|
||||
{
|
||||
ask_queue_t::iterator it = sAskQueue.begin();
|
||||
const LLUUID& key = it->first;
|
||||
const std::string& key_type = it->second;
|
||||
|
||||
ostr << '&' << key_type << '=' << key.asString() ;
|
||||
|
||||
keys[key]=key_type;
|
||||
request_count++;
|
||||
|
||||
sPendingQueue[key] = now;
|
||||
|
||||
if(ostr.tellp() > EXP_URL_SEND_THRESHOLD)
|
||||
{
|
||||
LL_DEBUGS("ExperienceCache") << "requestExperiences() query: " << ostr.str() << LL_ENDL;
|
||||
LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys));
|
||||
ostr.clear();
|
||||
ostr.str(sLookupURL);
|
||||
ostr << "?page_size=" << PAGE_SIZE;
|
||||
keys.clear();
|
||||
}
|
||||
sAskQueue.erase(it);
|
||||
}
|
||||
|
||||
if(ostr.tellp() > sLookupURL.size())
|
||||
{
|
||||
LL_DEBUGS("ExperienceCache") << "requestExperiences() query 2: " << ostr.str() << LL_ENDL;
|
||||
LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys));
|
||||
}
|
||||
}
|
||||
|
||||
bool isRequestPending(const LLUUID& public_key)
|
||||
{
|
||||
bool isPending = false;
|
||||
const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
|
||||
|
||||
pending_queue_t::const_iterator it = sPendingQueue.find(public_key);
|
||||
|
||||
if(it != sPendingQueue.end())
|
||||
{
|
||||
F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
|
||||
isPending = (it->second > expire_time);
|
||||
}
|
||||
|
||||
return isPending;
|
||||
}
|
||||
|
||||
|
||||
void setLookupURL( const std::string& lookup_url )
|
||||
{
|
||||
sLookupURL = lookup_url;
|
||||
if(!sLookupURL.empty())
|
||||
{
|
||||
sLookupURL += "id/";
|
||||
}
|
||||
}
|
||||
|
||||
bool hasLookupURL()
|
||||
{
|
||||
return !sLookupURL.empty();
|
||||
}
|
||||
|
||||
void idle()
|
||||
{
|
||||
|
||||
const F32 SECS_BETWEEN_REQUESTS = 0.1f;
|
||||
if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Must be large relative to above
|
||||
const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
|
||||
if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
|
||||
{
|
||||
eraseExpired();
|
||||
}
|
||||
|
||||
|
||||
if(!sAskQueue.empty())
|
||||
{
|
||||
requestExperiences();
|
||||
}
|
||||
}
|
||||
|
||||
void erase( const LLUUID& key )
|
||||
{
|
||||
cache_t::iterator it = sCache.find(key);
|
||||
|
||||
if(it != sCache.end())
|
||||
{
|
||||
sCache.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void eraseExpired()
|
||||
{
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
cache_t::iterator it = sCache.begin();
|
||||
while (it != sCache.end())
|
||||
{
|
||||
cache_t::iterator cur = it;
|
||||
LLSD& exp = cur->second;
|
||||
++it;
|
||||
|
||||
if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
|
||||
{
|
||||
if(!exp.has(EXPERIENCE_ID))
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ;
|
||||
sCache.erase(cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID id = exp[EXPERIENCE_ID].asUUID();
|
||||
LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null;
|
||||
if(private_key.notNull() || !exp.has("DoesNotExist"))
|
||||
{
|
||||
fetch(id, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ;
|
||||
sCache.erase(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool fetch( const LLUUID& key, bool refresh/* = true*/ )
|
||||
{
|
||||
if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end()))
|
||||
{
|
||||
LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ;
|
||||
sAskQueue[key]=EXPERIENCE_ID;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void insert(const LLSD& experience_data )
|
||||
{
|
||||
if(experience_data.has(EXPERIENCE_ID))
|
||||
{
|
||||
processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL;
|
||||
}
|
||||
}
|
||||
static LLSD empty;
|
||||
const LLSD& get(const LLUUID& key)
|
||||
{
|
||||
if(key.isNull()) return empty;
|
||||
cache_t::const_iterator it = sCache.find(key);
|
||||
|
||||
if (it != sCache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
fetch(key);
|
||||
|
||||
return empty;
|
||||
}
|
||||
void get( const LLUUID& key, callback_slot_t slot )
|
||||
{
|
||||
if(key.isNull()) return;
|
||||
|
||||
cache_t::const_iterator it = sCache.find(key);
|
||||
if (it != sCache.end())
|
||||
{
|
||||
// ...name already exists in cache, fire callback now
|
||||
callback_signal_t signal;
|
||||
signal.connect(slot);
|
||||
|
||||
signal(it->second);
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(key);
|
||||
|
||||
// always store additional callback, even if request is pending
|
||||
signal_map_t::iterator sig_it = sSignalMap.find(key);
|
||||
if (sig_it == sSignalMap.end())
|
||||
{
|
||||
// ...new callback for this id
|
||||
callback_signal_t* signal = new callback_signal_t();
|
||||
signal->connect(slot);
|
||||
sSignalMap[key] = signal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...existing callback, bind additional slot
|
||||
callback_signal_t* signal = sig_it->second;
|
||||
signal->connect(slot);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LLExperienceCache::mapKeys( const LLSD& legacyKeys )
|
||||
{
|
||||
LLSD::array_const_iterator exp = legacyKeys.beginArray();
|
||||
for(/**/ ; exp != legacyKeys.endArray() ; ++exp)
|
||||
{
|
||||
if(exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY))
|
||||
{
|
||||
privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()]=(*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found)
|
||||
{
|
||||
if (private_key.isNull())
|
||||
return LLUUID::null;
|
||||
|
||||
KeyMap::const_iterator it=privateToPublicKeyMap.find(private_key);
|
||||
if(it == privateToPublicKeyMap.end())
|
||||
{
|
||||
if(null_if_not_found)
|
||||
{
|
||||
return LLUUID::null;
|
||||
}
|
||||
return private_key;
|
||||
}
|
||||
LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL;
|
||||
return it->second;
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* @file llexperiencecache.h
|
||||
* @brief Caches information relating to experience keys
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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_LLEXPERIENCECACHE_H
|
||||
#define LL_LLEXPERIENCECACHE_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
class LLSD;
|
||||
class LLUUID;
|
||||
|
||||
|
||||
|
||||
namespace LLExperienceCache
|
||||
{
|
||||
const std::string PRIVATE_KEY = "private_id";
|
||||
const std::string MISSING = "DoesNotExist";
|
||||
|
||||
const std::string AGENT_ID = "agent_id";
|
||||
const std::string GROUP_ID = "group_id";
|
||||
const std::string EXPERIENCE_ID = "public_id";
|
||||
const std::string NAME = "name";
|
||||
const std::string PROPERTIES = "properties";
|
||||
const std::string EXPIRES = "expiration";
|
||||
const std::string DESCRIPTION = "description";
|
||||
const std::string QUOTA = "quota";
|
||||
const std::string MATURITY = "maturity";
|
||||
const std::string METADATA = "extended_metadata";
|
||||
const std::string SLURL = "slurl";
|
||||
|
||||
|
||||
// should be in sync with experience-api/experiences/models.py
|
||||
const int PROPERTY_INVALID = 1 << 0;
|
||||
const int PROPERTY_PRIVILEGED = 1 << 3;
|
||||
const int PROPERTY_GRID = 1 << 4;
|
||||
const int PROPERTY_PRIVATE = 1 << 5;
|
||||
const int PROPERTY_DISABLED = 1 << 6;
|
||||
const int PROPERTY_SUSPENDED = 1 << 7;
|
||||
|
||||
|
||||
// default values
|
||||
const static F64 DEFAULT_EXPIRATION = 600.0;
|
||||
const static S32 DEFAULT_QUOTA = 128; // this is megabytes
|
||||
|
||||
// Callback types for get() below
|
||||
typedef boost::signals2::signal<void (const LLSD& experience)>
|
||||
callback_signal_t;
|
||||
typedef callback_signal_t::slot_type callback_slot_t;
|
||||
typedef std::map<LLUUID, LLSD> cache_t;
|
||||
|
||||
|
||||
void setLookupURL(const std::string& lookup_url);
|
||||
bool hasLookupURL();
|
||||
|
||||
void setMaximumLookups(int maximumLookups);
|
||||
|
||||
void idle();
|
||||
void exportFile(std::ostream& ostr);
|
||||
void importFile(std::istream& istr);
|
||||
void initClass();
|
||||
void bootstrap(const LLSD& legacyKeys, int initialExpiration);
|
||||
|
||||
void erase(const LLUUID& key);
|
||||
bool fetch(const LLUUID& key, bool refresh=false);
|
||||
void insert(const LLSD& experience_data);
|
||||
const LLSD& get(const LLUUID& key);
|
||||
|
||||
// If name information is in cache, callback will be called immediately.
|
||||
void get(const LLUUID& key, callback_slot_t slot);
|
||||
|
||||
const cache_t& getCached();
|
||||
|
||||
// maps an experience private key to the experience id
|
||||
LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false);
|
||||
|
||||
};
|
||||
|
||||
#endif // LL_LLEXPERIENCECACHE_H
|
||||
|
|
@ -148,19 +148,20 @@ const U32 ESTATE_ACCESS_ALL = ESTATE_ACCESS_ALLOWED_AGENTS
|
|||
| ESTATE_ACCESS_BANNED_AGENTS
|
||||
| ESTATE_ACCESS_MANAGERS;
|
||||
|
||||
// for EstateOwnerRequest, estateaccessdelta message
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1 << 0;
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1 << 1;
|
||||
// for EstateOwnerRequest, estateaccessdelta, estateexperiencedelta messages
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1U << 0;
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1U << 1;
|
||||
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1 << 2;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1 << 3;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1 << 4;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1 << 5;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1 << 6;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1 << 7;
|
||||
const U32 ESTATE_ACCESS_MANAGER_ADD = 1 << 8;
|
||||
const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1 << 9;
|
||||
const U32 ESTATE_ACCESS_NO_REPLY = 1 << 10;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1U << 2;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1U << 3;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1U << 4;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1U << 5;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1U << 6;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1U << 7;
|
||||
const U32 ESTATE_ACCESS_MANAGER_ADD = 1U << 8;
|
||||
const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9;
|
||||
const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10;
|
||||
const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11;
|
||||
|
||||
const S32 ESTATE_MAX_MANAGERS = 10;
|
||||
const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access, banned
|
||||
|
|
@ -171,6 +172,26 @@ const U32 SWD_OTHERS_LAND_ONLY = (1 << 0);
|
|||
const U32 SWD_ALWAYS_RETURN_OBJECTS = (1 << 1);
|
||||
const U32 SWD_SCRIPTED_ONLY = (1 << 2);
|
||||
|
||||
// Controls experience key validity in the estate
|
||||
const U32 EXPERIENCE_KEY_TYPE_NONE = 0;
|
||||
const U32 EXPERIENCE_KEY_TYPE_BLOCKED = 1;
|
||||
const U32 EXPERIENCE_KEY_TYPE_ALLOWED = 2;
|
||||
const U32 EXPERIENCE_KEY_TYPE_TRUSTED = 3;
|
||||
|
||||
const U32 EXPERIENCE_KEY_TYPE_FIRST = EXPERIENCE_KEY_TYPE_BLOCKED;
|
||||
const U32 EXPERIENCE_KEY_TYPE_LAST = EXPERIENCE_KEY_TYPE_TRUSTED;
|
||||
|
||||
//
|
||||
const U32 ESTATE_EXPERIENCE_TRUSTED_ADD = 1U << 2;
|
||||
const U32 ESTATE_EXPERIENCE_TRUSTED_REMOVE = 1U << 3;
|
||||
const U32 ESTATE_EXPERIENCE_ALLOWED_ADD = 1U << 4;
|
||||
const U32 ESTATE_EXPERIENCE_ALLOWED_REMOVE = 1U << 5;
|
||||
const U32 ESTATE_EXPERIENCE_BLOCKED_ADD = 1U << 6;
|
||||
const U32 ESTATE_EXPERIENCE_BLOCKED_REMOVE = 1U << 7;
|
||||
|
||||
const S32 ESTATE_MAX_EXPERIENCE_IDS = 8;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1385,3 +1385,5 @@ char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance
|
|||
char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion");
|
||||
char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()->getString("AppearanceHover");
|
||||
char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight");
|
||||
char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience");
|
||||
char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID");
|
||||
|
|
|
|||
|
|
@ -1385,4 +1385,6 @@ extern char const* const _PREHASH_AppearanceVersion;
|
|||
extern char const* const _PREHASH_CofVersion;
|
||||
extern char const* const _PREHASH_AppearanceHover;
|
||||
extern char const* const _PREHASH_HoverHeight;
|
||||
extern char const* const _PREHASH_Experience;
|
||||
extern char const* const _PREHASH_ExperienceID;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -239,4 +239,23 @@ const U32 LSL_STATUS_INTERNAL_ERROR = 1999;
|
|||
// Start per-function errors below, starting at 2000:
|
||||
const U32 LSL_STATUS_WHITELIST_FAILED = 2001;
|
||||
|
||||
|
||||
const S32 LSL_XP_ERROR_NONE = 0;
|
||||
const S32 LSL_XP_ERROR_THROTTLED = 1;
|
||||
const S32 LSL_XP_ERROR_EXPERIENCES_DISABLED = 2;
|
||||
const S32 LSL_XP_ERROR_INVALID_PARAMETERS = 3;
|
||||
const S32 LSL_XP_ERROR_NOT_PERMITTED = 4;
|
||||
const S32 LSL_XP_ERROR_NO_EXPERIENCE = 5;
|
||||
const S32 LSL_XP_ERROR_NOT_FOUND = 6;
|
||||
const S32 LSL_XP_ERROR_INVALID_EXPERIENCE = 7;
|
||||
const S32 LSL_XP_ERROR_EXPERIENCE_DISABLED = 8;
|
||||
const S32 LSL_XP_ERROR_EXPERIENCE_SUSPENDED = 9;
|
||||
const S32 LSL_XP_ERROR_UNKNOWN_ERROR = 10;
|
||||
const S32 LSL_XP_ERROR_QUOTA_EXCEEDED = 11;
|
||||
const S32 LSL_XP_ERROR_STORE_DISABLED = 12;
|
||||
const S32 LSL_XP_ERROR_STORAGE_EXCEPTION = 13;
|
||||
const S32 LSL_XP_ERROR_KEY_NOT_FOUND = 14;
|
||||
const S32 LSL_XP_ERROR_RETRY_UPDATE = 15;
|
||||
const S32 LSL_XP_ERROR_MATURITY_EXCEEDED = 16;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -678,7 +678,7 @@ void LLNotification::respond(const LLSD& response)
|
|||
// and then call it
|
||||
functor(asLLSD(), response);
|
||||
}
|
||||
else
|
||||
else if (mCombinedNotifications.empty())
|
||||
{
|
||||
// no registered responder
|
||||
return;
|
||||
|
|
@ -700,6 +700,14 @@ void LLNotification::respond(const LLSD& response)
|
|||
}
|
||||
}
|
||||
|
||||
for (std::vector<LLNotificationPtr>::const_iterator it = mCombinedNotifications.begin(); it != mCombinedNotifications.end(); ++it)
|
||||
{
|
||||
if ((*it))
|
||||
{
|
||||
(*it)->respond(response);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
@ -1322,6 +1330,28 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case LLNotification::COMBINE_WITH_NEW:
|
||||
// Add to the existing unique notification with the data from this particular instance...
|
||||
// This guarantees that duplicate notifications will be collapsed to the one
|
||||
// most recently triggered
|
||||
for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
|
||||
existing_it != mUniqueNotifications.end();
|
||||
++existing_it)
|
||||
{
|
||||
LLNotificationPtr existing_notification = existing_it->second;
|
||||
if (pNotif != existing_notification
|
||||
&& pNotif->isEquivalentTo(existing_notification))
|
||||
{
|
||||
// copy the notifications from the newest instance into the oldest
|
||||
existing_notification->mCombinedNotifications.push_back(pNotif);
|
||||
existing_notification->mCombinedNotifications.insert(existing_notification->mCombinedNotifications.end(),
|
||||
pNotif->mCombinedNotifications.begin(), pNotif->mCombinedNotifications.end());
|
||||
|
||||
// pop up again
|
||||
existing_notification->update();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LLNotification::KEEP_OLD:
|
||||
break;
|
||||
case LLNotification::CANCEL_OLD:
|
||||
|
|
|
|||
|
|
@ -414,6 +414,9 @@ private:
|
|||
using the same mechanism.
|
||||
*/
|
||||
bool mTemporaryResponder;
|
||||
|
||||
// keep track of other notifications combined with COMBINE_WITH_NEW
|
||||
std::vector<LLNotificationPtr> mCombinedNotifications;
|
||||
|
||||
void init(const std::string& template_name, const LLSD& form_elements);
|
||||
|
||||
|
|
@ -560,6 +563,7 @@ public:
|
|||
typedef enum e_combine_behavior
|
||||
{
|
||||
REPLACE_WITH_NEW,
|
||||
COMBINE_WITH_NEW,
|
||||
KEEP_OLD,
|
||||
CANCEL_OLD
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ struct LLNotificationTemplate
|
|||
static void declareValues()
|
||||
{
|
||||
declare("replace_with_new", LLNotification::REPLACE_WITH_NEW);
|
||||
declare("combine_with_new", LLNotification::COMBINE_WITH_NEW);
|
||||
declare("keep_old", LLNotification::KEEP_OLD);
|
||||
declare("cancel_old", LLNotification::CANCEL_OLD);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2094,3 +2094,8 @@ void LLTabContainer::commitHoveredButton(S32 x, S32 y)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLTabContainer::getTotalTabWidth() const
|
||||
{
|
||||
return mTotalTabWidth;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,8 @@ public:
|
|||
LLPanel* getPanelByIndex(S32 index);
|
||||
S32 getIndexForPanel(LLPanel* panel);
|
||||
S32 getPanelIndexByTitle(const std::string& title);
|
||||
LLPanel* getPanelByName(const std::string& name);
|
||||
LLPanel* getPanelByName(const std::string& name);
|
||||
S32 getTotalTabWidth() const;
|
||||
void setCurrentTabName(const std::string& name);
|
||||
|
||||
void selectFirstTab();
|
||||
|
|
@ -287,7 +288,7 @@ private:
|
|||
|
||||
S32 mMaxTabWidth;
|
||||
S32 mTotalTabWidth;
|
||||
S32 mTabHeight;
|
||||
S32 mTabHeight;
|
||||
|
||||
// Padding under the text labels of tab buttons
|
||||
S32 mLabelPadBottom;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "lltrans.h"
|
||||
#include "lluicolortable.h"
|
||||
#include "message.h"
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
|
||||
|
||||
|
|
@ -1399,3 +1400,57 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)
|
|||
LLStringUtil::trim(mIcon);
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile()
|
||||
{
|
||||
mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*",
|
||||
boost::regex::perl|boost::regex::icase);
|
||||
mIcon = "Generic_Experience";
|
||||
mMenuName = "menu_url_experience.xml";
|
||||
}
|
||||
|
||||
std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const LLUrlLabelCallback &cb )
|
||||
{
|
||||
if (!gCacheName)
|
||||
{
|
||||
// probably at the login screen, use short string for layout
|
||||
return LLTrans::getString("LoadingData");
|
||||
}
|
||||
|
||||
std::string experience_id_string = getIDStringFromUrl(url);
|
||||
if (experience_id_string.empty())
|
||||
{
|
||||
// something went wrong, just give raw url
|
||||
return unescapeUrl(url);
|
||||
}
|
||||
|
||||
LLUUID experience_id(experience_id_string);
|
||||
if (experience_id.isNull())
|
||||
{
|
||||
return LLTrans::getString("ExperienceNameNull");
|
||||
}
|
||||
|
||||
const LLSD& experience_details = LLExperienceCache::get(experience_id);
|
||||
if(!experience_details.isUndefined())
|
||||
{
|
||||
std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString();
|
||||
return experience_name_string.empty() ? LLTrans::getString("ExperienceNameUntitled") : experience_name_string;
|
||||
}
|
||||
|
||||
addObserver(experience_id_string, url, cb);
|
||||
LLExperienceCache::get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1));
|
||||
return LLTrans::getString("LoadingData");
|
||||
|
||||
}
|
||||
|
||||
void LLUrlEntryExperienceProfile::onExperienceDetails( const LLSD& experience_details )
|
||||
{
|
||||
std::string name = experience_details[LLExperienceCache::NAME].asString();
|
||||
if(name.empty())
|
||||
{
|
||||
name = LLTrans::getString("ExperienceNameUntitled");
|
||||
}
|
||||
callObservers(experience_details[LLExperienceCache::EXPERIENCE_ID].asString(), name, LLStringUtil::null);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -308,6 +308,20 @@ private:
|
|||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryExperienceProfile Describes a Second Life experience profile Url, e.g.,
|
||||
/// secondlife:///app/experience/0e346d8b-4433-4d66-a6b0-fd37083abc4c/profile
|
||||
/// that displays the experience name
|
||||
class LLUrlEntryExperienceProfile : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryExperienceProfile();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
private:
|
||||
void onExperienceDetails(const LLSD& experience_details);
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
|
||||
/// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ LLUrlRegistry::LLUrlRegistry()
|
|||
registerUrl(new LLUrlEntryPlace());
|
||||
registerUrl(new LLUrlEntryInventory());
|
||||
registerUrl(new LLUrlEntryObjectIM());
|
||||
registerUrl(new LLUrlEntryExperienceProfile());
|
||||
//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,
|
||||
//so it should be registered in the end of list
|
||||
registerUrl(new LLUrlEntrySL());
|
||||
|
|
|
|||
|
|
@ -32,9 +32,23 @@
|
|||
#include "lltut.h"
|
||||
#include "../lluicolortable.h"
|
||||
#include "../llrender/lluiimage.h"
|
||||
#include "../llmessage/llexperiencecache.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
|
||||
namespace LLExperienceCache
|
||||
{
|
||||
const LLSD& get( const LLUUID& key)
|
||||
{
|
||||
static LLSD boo;
|
||||
return boo;
|
||||
}
|
||||
|
||||
void get( const LLUUID& key, callback_slot_t slot ){}
|
||||
|
||||
}
|
||||
|
||||
typedef std::map<std::string, LLControlGroup*> settings_map_t;
|
||||
settings_map_t LLUI::sSettingGroups;
|
||||
|
||||
|
|
|
|||
|
|
@ -355,6 +355,10 @@ typedef enum e_lscript_state_event_type
|
|||
LSTT_REMOTE_DATA,
|
||||
LSTT_HTTP_RESPONSE,
|
||||
LSTT_HTTP_REQUEST,
|
||||
LSTT_EXPERMISSIONS,
|
||||
LSTT_TRANSACTION_RESULT,
|
||||
LSTT_PATH_UPDATE,
|
||||
LSTT_EXPERMISSIONS_DENIED,
|
||||
LSTT_EOF,
|
||||
|
||||
LSTT_STATE_BEGIN = LSTT_STATE_ENTRY,
|
||||
|
|
@ -397,7 +401,11 @@ const U64 LSCRIPTStateBitField[LSTT_EOF] =
|
|||
0x0000000040000000, // LSTT_OBJECT_REZ
|
||||
0x0000000080000000, // LSTT_REMOTE_DATA
|
||||
0x0000000100000000LL, // LSTT_HTTP_RESPOSE
|
||||
0x0000000200000000LL // LSTT_HTTP_REQUEST
|
||||
0x0000000200000000LL, // LSTT_HTTP_REQUEST
|
||||
0x0000000400000000LL, // LSTT_EXPERMISSIONS
|
||||
0x0000000800000000LL, // LSTT_TRANSACTION_RESULT
|
||||
0x0000001000000000LL, // LSTT_PATH_UPDATE
|
||||
0x0000002000000000LL, //LSTT_EXPERMISSIONS_DENIED
|
||||
};
|
||||
|
||||
inline S32 get_event_handler_jump_position(U64 bit_field, LSCRIPTStateEventType type)
|
||||
|
|
@ -511,6 +519,7 @@ typedef enum e_lscript_runtime_faults
|
|||
LSRF_TOO_MANY_LISTENS,
|
||||
LSRF_NESTING_LISTS,
|
||||
LSRF_CLI,
|
||||
LSRF_INVALID_STATE,
|
||||
LSRF_EOF
|
||||
} LSCRIPTRunTimeFaults;
|
||||
|
||||
|
|
@ -551,10 +560,10 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
|
|||
(0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA
|
||||
(0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA
|
||||
(0x1 << 12),// SCRIPT_PERMISSION_TELEPORT
|
||||
(0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE,
|
||||
(0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT,
|
||||
(0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS,
|
||||
(0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS,
|
||||
(0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE
|
||||
(0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT
|
||||
(0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS
|
||||
(0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS
|
||||
};
|
||||
|
||||
// http_request string constants
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ int yyerror(const char *fmt, ...);
|
|||
"money" { count(); return(MONEY); }
|
||||
"email" { count(); return(EMAIL); }
|
||||
"run_time_permissions" { count(); return(RUN_TIME_PERMISSIONS); }
|
||||
"experience_permissions" { count(); return(EXPERIENCE_PERMISSIONS); }
|
||||
"experience_permissions_denied" { count(); return(EXPERIENCE_PERMISSIONS_DENIED); }
|
||||
"changed" { count(); return(INVENTORY); }
|
||||
"attach" { count(); return(ATTACH); }
|
||||
"dataserver" { count(); return(DATASERVER); }
|
||||
|
|
@ -393,7 +395,6 @@ int yyerror(const char *fmt, ...);
|
|||
"PSYS_PART_END_ALPHA" { count(); yylval.ival = LLPS_PART_END_ALPHA; return (INTEGER_CONSTANT); }
|
||||
"PSYS_PART_END_SCALE" { count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }
|
||||
"PSYS_PART_MAX_AGE" { count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); }
|
||||
|
||||
"PSYS_PART_BLEND_FUNC_SOURCE" { count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); }
|
||||
"PSYS_PART_BLEND_FUNC_DEST" { count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); }
|
||||
"PSYS_PART_START_GLOW" { count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); }
|
||||
|
|
@ -419,7 +420,6 @@ int yyerror(const char *fmt, ...);
|
|||
"PSYS_PART_BF_SOURCE_ALPHA" { count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
|
||||
"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA" { count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
|
||||
|
||||
|
||||
"PSYS_SRC_MAX_AGE" { count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); }
|
||||
"PSYS_SRC_PATTERN" { count(); yylval.ival = LLPS_SRC_PATTERN; return(INTEGER_CONSTANT); }
|
||||
"PSYS_SRC_INNERANGLE" { count(); yylval.ival = LLPS_SRC_INNERANGLE; return(INTEGER_CONSTANT); }
|
||||
|
|
@ -737,6 +737,24 @@ int yyerror(const char *fmt, ...);
|
|||
"STATUS_INTERNAL_ERROR" { count(); yylval.ival = LSL_STATUS_INTERNAL_ERROR; return(INTEGER_CONSTANT); }
|
||||
"STATUS_WHITELIST_FAILED" { count(); yylval.ival = LSL_STATUS_WHITELIST_FAILED; return(INTEGER_CONSTANT); }
|
||||
|
||||
"XP_ERROR_NONE" { count(); yylval.ival = LSL_XP_ERROR_NONE ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_THROTTLED" { count(); yylval.ival = LSL_XP_ERROR_THROTTLED ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_EXPERIENCES_DISABLED" { count(); yylval.ival = LSL_XP_ERROR_EXPERIENCES_DISABLED; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_INVALID_PARAMETERS" { count(); yylval.ival = LSL_XP_ERROR_INVALID_PARAMETERS ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_NOT_PERMITTED" { count(); yylval.ival = LSL_XP_ERROR_NOT_PERMITTED ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_NO_EXPERIENCE" { count(); yylval.ival = LSL_XP_ERROR_NO_EXPERIENCE ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_NOT_FOUND" { count(); yylval.ival = LSL_XP_ERROR_NOT_FOUND ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_INVALID_EXPERIENCE" { count(); yylval.ival = LSL_XP_ERROR_INVALID_EXPERIENCE ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_EXPERIENCE_DISABLED" { count(); yylval.ival = LSL_XP_ERROR_EXPERIENCE_DISABLED ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_EXPERIENCE_SUSPENDED" { count(); yylval.ival = LSL_XP_ERROR_EXPERIENCE_SUSPENDED; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_UNKNOWN_ERROR" { count(); yylval.ival = LSL_XP_ERROR_UNKNOWN_ERROR ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_QUOTA_EXCEEDED" { count(); yylval.ival = LSL_XP_ERROR_QUOTA_EXCEEDED ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_STORE_DISABLED" { count(); yylval.ival = LSL_XP_ERROR_STORE_DISABLED ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_STORAGE_EXCEPTION" { count(); yylval.ival = LSL_XP_ERROR_STORAGE_EXCEPTION ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_KEY_NOT_FOUND" { count(); yylval.ival = LSL_XP_ERROR_KEY_NOT_FOUND ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_RETRY_UPDATE" { count(); yylval.ival = LSL_XP_ERROR_RETRY_UPDATE ; return (INTEGER_CONSTANT); }
|
||||
"XP_ERROR_MATURITY_EXCEEDED" { count(); yylval.ival = LSL_XP_ERROR_MATURITY_EXCEEDED ; return (INTEGER_CONSTANT); }
|
||||
|
||||
{L}({L}|{N})* { count(); yylval.sval = new char[strlen(yytext) + 1]; strcpy(yylval.sval, yytext); return(IDENTIFIER); }
|
||||
|
||||
{N}+{E} { count(); yylval.fval = (F32)atof(yytext); return(FP_CONSTANT); }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#pragma warning (disable : 4702) // warning C4702: unreachable code
|
||||
#pragma warning( disable : 4065 ) // warning: switch statement contains 'default' but no 'case' labels
|
||||
#endif
|
||||
|
||||
%}
|
||||
|
||||
%union
|
||||
|
|
@ -75,6 +74,8 @@
|
|||
%token MONEY
|
||||
%token EMAIL
|
||||
%token RUN_TIME_PERMISSIONS
|
||||
%token EXPERIENCE_PERMISSIONS
|
||||
%token EXPERIENCE_PERMISSIONS_DENIED
|
||||
%token INVENTORY
|
||||
%token ATTACH
|
||||
%token DATASERVER
|
||||
|
|
@ -180,6 +181,8 @@
|
|||
%type <event> money
|
||||
%type <event> email
|
||||
%type <event> run_time_permissions
|
||||
%type <event> experience_permissions
|
||||
%type <event> experience_permissions_denied
|
||||
%type <event> inventory
|
||||
%type <event> attach
|
||||
%type <event> dataserver
|
||||
|
|
@ -788,6 +791,16 @@ event
|
|||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
| experience_permissions compound_statement
|
||||
{
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
| experience_permissions_denied compound_statement
|
||||
{
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
| inventory compound_statement
|
||||
{
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
|
|
@ -1040,6 +1053,28 @@ run_time_permissions
|
|||
}
|
||||
;
|
||||
|
||||
experience_permissions
|
||||
: EXPERIENCE_PERMISSIONS '(' LLKEY IDENTIFIER ')'
|
||||
{
|
||||
LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4);
|
||||
gAllocationManager->addAllocation(id1);
|
||||
$$ = new LLScriptEXPEvent(gLine, gColumn, id1);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
;
|
||||
|
||||
experience_permissions_denied
|
||||
: EXPERIENCE_PERMISSIONS_DENIED '(' LLKEY IDENTIFIER ',' INTEGER IDENTIFIER ')'
|
||||
{
|
||||
LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4);
|
||||
gAllocationManager->addAllocation(id1);
|
||||
LLScriptIdentifier *id2 = new LLScriptIdentifier(gLine, gColumn, $7);
|
||||
gAllocationManager->addAllocation(id2);
|
||||
$$ = new LLScriptEXPDeniedEvent(gLine, gColumn, id1, id2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
;
|
||||
|
||||
inventory
|
||||
: INVENTORY '(' INTEGER IDENTIFIER ')'
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3844,6 +3844,156 @@ S32 LLScriptNotAtTarget::getSize()
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void LLScriptEXPEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
|
||||
{
|
||||
if (gErrorToText.getErrors())
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch(pass)
|
||||
{
|
||||
case LSCP_PRETTY_PRINT:
|
||||
case LSCP_EMIT_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions( key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )\n");
|
||||
break;
|
||||
case LSCP_SCOPE_PASS1:
|
||||
checkForDuplicateHandler(fp, this, scope, "experience_permissions");
|
||||
if (scope->checkEntry(mName->mName))
|
||||
{
|
||||
gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
|
||||
}
|
||||
break;
|
||||
case LSCP_RESOURCE:
|
||||
{
|
||||
// we're just tryng to determine how much space the variable needs
|
||||
if (mName->mScopeEntry)
|
||||
{
|
||||
mName->mScopeEntry->mOffset = (S32)count;
|
||||
mName->mScopeEntry->mSize = 4;
|
||||
count += mName->mScopeEntry->mSize;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LSCP_EMIT_BYTE_CODE:
|
||||
{
|
||||
#ifdef LSL_INCLUDE_DEBUG_INFO
|
||||
char name[] = "experience_permissions";
|
||||
chunk->addBytes(name, strlen(name) + 1);
|
||||
chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case LSCP_EMIT_CIL_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions( valuetype [ScriptTypes]LindenLab.SecondLife.Key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )");
|
||||
break;
|
||||
default:
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLScriptEXPEvent::getSize()
|
||||
{
|
||||
// key = 4
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
void LLScriptEXPDeniedEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
|
||||
{
|
||||
if (gErrorToText.getErrors())
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch(pass)
|
||||
{
|
||||
case LSCP_PRETTY_PRINT:
|
||||
case LSCP_EMIT_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions_denied( key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, ", integer ");
|
||||
mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )\n");
|
||||
break;
|
||||
case LSCP_SCOPE_PASS1:
|
||||
checkForDuplicateHandler(fp, this, scope, "experience_permissions_denied");
|
||||
if (scope->checkEntry(mName->mName))
|
||||
{
|
||||
gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
|
||||
}
|
||||
if (scope->checkEntry(mReason->mName))
|
||||
{
|
||||
gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
mReason->mScopeEntry = scope->addEntry(mReason->mName, LIT_VARIABLE, LST_INTEGER);
|
||||
}
|
||||
break;
|
||||
case LSCP_RESOURCE:
|
||||
{
|
||||
// we're just trying to determine how much space the variable needs
|
||||
if (mName->mScopeEntry)
|
||||
{
|
||||
mName->mScopeEntry->mOffset = (S32)count;
|
||||
mName->mScopeEntry->mSize = 4;
|
||||
count += mName->mScopeEntry->mSize;
|
||||
|
||||
mReason->mScopeEntry->mOffset = (S32)count;
|
||||
mReason->mScopeEntry->mSize = 4;
|
||||
count += mReason->mScopeEntry->mSize;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LSCP_EMIT_BYTE_CODE:
|
||||
{
|
||||
#ifdef LSL_INCLUDE_DEBUG_INFO
|
||||
char name[] = "experience_permissions_denied";
|
||||
chunk->addBytes(name, strlen(name) + 1);
|
||||
chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
|
||||
chunk->addBytes(mReason->mName, strlen(mReason->mName) + 1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case LSCP_EMIT_CIL_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions_denied( valuetype [ScriptTypes]LindenLab.SecondLife.Key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, ", int32 ");
|
||||
mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )");
|
||||
break;
|
||||
default:
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLScriptEXPDeniedEvent::getSize()
|
||||
{
|
||||
// key = 4 + integer
|
||||
return LSCRIPTDataSize[LST_KEY]+LSCRIPTDataSize[LST_INTEGER];
|
||||
}
|
||||
|
||||
void LLScriptAtRotTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
|
||||
{
|
||||
if (gErrorToText.getErrors())
|
||||
|
|
@ -8569,6 +8719,7 @@ void LLScriptReturn::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa
|
|||
}
|
||||
}
|
||||
prunearg = TRUE;
|
||||
break;
|
||||
case LSCP_TYPE:
|
||||
// if there is a return expression, it must be promotable to the return type of the function
|
||||
if (mExpression)
|
||||
|
|
@ -9767,7 +9918,13 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom
|
|||
mScopeEntry->mFunctionArgs.addType(LST_STRING);
|
||||
mScopeEntry->mFunctionArgs.addType(LST_STRING);
|
||||
break;
|
||||
|
||||
case LSTT_EXPERMISSIONS:
|
||||
mScopeEntry->mFunctionArgs.addType(LST_KEY);
|
||||
break;
|
||||
case LSTT_EXPERMISSIONS_DENIED:
|
||||
mScopeEntry->mFunctionArgs.addType(LST_KEY);
|
||||
mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -627,6 +627,39 @@ public:
|
|||
LLScriptIdentifier *mRTPermissions;
|
||||
};
|
||||
|
||||
class LLScriptEXPEvent : public LLScriptEvent
|
||||
{
|
||||
public:
|
||||
LLScriptEXPEvent(S32 line, S32 col, LLScriptIdentifier *name)
|
||||
: LLScriptEvent(line, col, LSTT_EXPERMISSIONS), mName(name)
|
||||
{
|
||||
}
|
||||
|
||||
~LLScriptEXPEvent() {}
|
||||
|
||||
void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);
|
||||
S32 getSize();
|
||||
|
||||
LLScriptIdentifier *mName;
|
||||
};
|
||||
|
||||
class LLScriptEXPDeniedEvent : public LLScriptEvent
|
||||
{
|
||||
public:
|
||||
LLScriptEXPDeniedEvent(S32 line, S32 col, LLScriptIdentifier *name, LLScriptIdentifier *reason)
|
||||
: LLScriptEvent(line, col, LSTT_EXPERMISSIONS_DENIED), mName(name), mReason(reason)
|
||||
{
|
||||
}
|
||||
|
||||
~LLScriptEXPDeniedEvent() {}
|
||||
|
||||
void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);
|
||||
S32 getSize();
|
||||
|
||||
LLScriptIdentifier *mName;
|
||||
LLScriptIdentifier *mReason;
|
||||
};
|
||||
|
||||
class LLScriptChatEvent : public LLScriptEvent
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ set(viewer_SOURCE_FILES
|
|||
lleventnotifier.cpp
|
||||
lleventpoll.cpp
|
||||
llexpandabletextbox.cpp
|
||||
llexperienceassociationresponder.cpp
|
||||
llexperiencelog.cpp
|
||||
llexternaleditor.cpp
|
||||
llface.cpp
|
||||
llfacebookconnect.cpp
|
||||
|
|
@ -236,6 +238,9 @@ set(viewer_SOURCE_FILES
|
|||
llfloatereditwater.cpp
|
||||
llfloaterenvironmentsettings.cpp
|
||||
llfloaterevent.cpp
|
||||
llfloaterexperiencepicker.cpp
|
||||
llfloaterexperienceprofile.cpp
|
||||
llfloaterexperiences.cpp
|
||||
llfloaterfacebook.cpp
|
||||
llfloaterflickr.cpp
|
||||
llfloaterfonttest.cpp
|
||||
|
|
@ -415,11 +420,16 @@ set(viewer_SOURCE_FILES
|
|||
llpanelclassified.cpp
|
||||
llpanelcontents.cpp
|
||||
llpaneleditwearable.cpp
|
||||
llpanelexperiencelisteditor.cpp
|
||||
llpanelexperiencelog.cpp
|
||||
llpanelexperiencepicker.cpp
|
||||
llpanelexperiences.cpp
|
||||
llpanelface.cpp
|
||||
llpanelgenerictip.cpp
|
||||
llpanelgroup.cpp
|
||||
llpanelgroupbulk.cpp
|
||||
llpanelgroupbulkban.cpp
|
||||
llpanelgroupexperiences.cpp
|
||||
llpanelgroupgeneral.cpp
|
||||
llpanelgroupinvite.cpp
|
||||
llpanelgrouplandmoney.cpp
|
||||
|
|
@ -798,6 +808,8 @@ set(viewer_HEADER_FILES
|
|||
lleventnotifier.h
|
||||
lleventpoll.h
|
||||
llexpandabletextbox.h
|
||||
llexperienceassociationresponder.h
|
||||
llexperiencelog.h
|
||||
llexternaleditor.h
|
||||
llface.h
|
||||
llfacebookconnect.h
|
||||
|
|
@ -838,6 +850,9 @@ set(viewer_HEADER_FILES
|
|||
llfloatereditwater.h
|
||||
llfloaterenvironmentsettings.h
|
||||
llfloaterevent.h
|
||||
llfloaterexperiencepicker.h
|
||||
llfloaterexperienceprofile.h
|
||||
llfloaterexperiences.h
|
||||
llfloaterfacebook.h
|
||||
llfloaterflickr.h
|
||||
llfloaterfonttest.h
|
||||
|
|
@ -1010,12 +1025,17 @@ set(viewer_HEADER_FILES
|
|||
llpanelclassified.h
|
||||
llpanelcontents.h
|
||||
llpaneleditwearable.h
|
||||
llpanelexperiencelisteditor.h
|
||||
llpanelexperiencelog.h
|
||||
llpanelexperiencepicker.h
|
||||
llpanelexperiences.h
|
||||
llpanelface.h
|
||||
llpanelgenerictip.h
|
||||
llpanelgroup.h
|
||||
llpanelgroupbulk.h
|
||||
llpanelgroupbulkimpl.h
|
||||
llpanelgroupbulkban.h
|
||||
llpanelgroupexperiences.h
|
||||
llpanelgroupgeneral.h
|
||||
llpanelgroupinvite.h
|
||||
llpanelgrouplandmoney.h
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.7.31
|
||||
3.8.1
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ remote_data remote_data(integer event_type, key channel, key message_id, str
|
|||
http_response http_response(key request_id, integer status, list metadata, string body):Triggered when task receives a response to one of its llHTTPRequests
|
||||
http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL
|
||||
|
||||
|
||||
# integer constants
|
||||
[word .1, .1, .5]
|
||||
TRUE Integer constant for Boolean operations
|
||||
|
|
@ -714,6 +715,25 @@ TEXTURE_TRANSPARENT UUID for the "White - Transparent" texture
|
|||
URL_REQUEST_GRANTED Used with http_request when a public URL is successfully granted
|
||||
URL_REQUEST_DENIED Used with http_request when a public URL is not available
|
||||
|
||||
XP_ERROR_NONE No error was detected
|
||||
XP_ERROR_THROTTLED The call failed due to too many recent calls.
|
||||
XP_ERROR_EXPERIENCES_DISABLED The region currently has experiences disabled.
|
||||
XP_ERROR_INVALID_PARAMETERS One of the string arguments was too big to fit in the key-value store.
|
||||
XP_ERROR_NOT_PERMITTED This experience is not allowed to run on the current region.
|
||||
XP_ERROR_NO_EXPERIENCE This script is not associated with an experience.
|
||||
XP_ERROR_NOT_FOUND The sim was unable to verify the validity of the experience. Retrying after a short wait is advised.
|
||||
XP_ERROR_INVALID_EXPERIENCE The script is associated with an experience that no longer exists.
|
||||
XP_ERROR_EXPERIENCE_DISABLED The experience owner has temporarily disabled the experience.
|
||||
XP_ERROR_EXPERIENCE_SUSPENDED The experience has been suspended by Linden Customer Support.
|
||||
XP_ERROR_QUOTA_EXCEEDED An attempted write data to the key-value store failed due to the data quota being met.
|
||||
XP_ERROR_STORE_DISABLED The key-value store is currently disabled on this region.
|
||||
XP_ERROR_STORAGE_EXCEPTION Unable to communicate with the key-value store.
|
||||
XP_ERROR_KEY_NOT_FOUND The requested key does not exist.
|
||||
XP_ERROR_RETRY_UPDATE A checked update failed due to an out of date request.
|
||||
XP_ERROR_MATURITY_EXCEEDED The request failed due to agent content preferences.
|
||||
XP_ERROR_UNKNOWN_ERROR Other unknown error.
|
||||
|
||||
|
||||
# float constants
|
||||
[word .3, .1, .5]
|
||||
PI 3.1415926535897932384626433832795
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>300</real>
|
||||
<real>300.0</real>
|
||||
</map>
|
||||
<key>AckCollectTime</key>
|
||||
<map>
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1</real>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>AdvanceSnapshot</key>
|
||||
<map>
|
||||
|
|
@ -1651,7 +1651,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>100</real>
|
||||
<integer>100</integer>
|
||||
</map>
|
||||
<key>ChatLoadGroupTimeout</key>
|
||||
<map>
|
||||
|
|
@ -4271,7 +4271,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>3</real>
|
||||
<real>3.0</real>
|
||||
</map>
|
||||
<key>FullScreenAutoDetectAspectRatio</key>
|
||||
<map>
|
||||
|
|
@ -6286,7 +6286,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MeshEnabled</key>
|
||||
<map>
|
||||
|
|
@ -6297,7 +6297,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<real>1</real>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>MeshImportUseSLM</key>
|
||||
<map>
|
||||
|
|
@ -6308,7 +6308,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<real>1</real>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>MeshUploadLogXML</key>
|
||||
<map>
|
||||
|
|
@ -6319,7 +6319,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MeshUploadFakeErrors</key>
|
||||
<map>
|
||||
|
|
@ -6330,7 +6330,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MeshUploadTimeOut</key>
|
||||
<map>
|
||||
|
|
@ -6341,7 +6341,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>600</real>
|
||||
<integer>600</integer>
|
||||
</map>
|
||||
<key>MigrateCacheDirectory</key>
|
||||
<map>
|
||||
|
|
@ -8565,7 +8565,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>64</real>
|
||||
<real>64.0</real>
|
||||
</map>
|
||||
<key>RenderCubeMap</key>
|
||||
<map>
|
||||
|
|
@ -8701,7 +8701,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>16</real>
|
||||
<integer>16</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderEdgeDepthCutoff</key>
|
||||
|
|
@ -8747,7 +8747,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>4</real>
|
||||
<real>4.0</real>
|
||||
</map>
|
||||
<key>RenderDeferredSpotShadowBias</key>
|
||||
<map>
|
||||
|
|
@ -8814,7 +8814,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
|
||||
<key>RenderDepthPrePass</key>
|
||||
|
|
@ -9008,7 +9008,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderSpecularResX</key>
|
||||
|
|
@ -9020,7 +9020,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>1024</real>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderSpecularResY</key>
|
||||
|
|
@ -9032,7 +9032,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>256</real>
|
||||
<integer>256</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderSpecularExponent</key>
|
||||
|
|
@ -9188,7 +9188,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>4</real>
|
||||
<integer>4</integer>
|
||||
</map>
|
||||
<key>RenderShadowBlurDistFactor</key>
|
||||
<map>
|
||||
|
|
@ -9355,9 +9355,9 @@
|
|||
<string>Vector3</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>RenderGlowMaxExtractAlpha</key>
|
||||
|
|
@ -9958,7 +9958,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteLogging</key>
|
||||
<map>
|
||||
|
|
@ -10180,7 +10180,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>250000</real>
|
||||
<integer>250000</integer>
|
||||
</map>
|
||||
<key>MeshMetaDataDiscount</key>
|
||||
<map>
|
||||
|
|
@ -10191,7 +10191,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>384</real>
|
||||
<integer>384</integer>
|
||||
</map>
|
||||
<key>MeshMinimumByteSize</key>
|
||||
<map>
|
||||
|
|
@ -10202,7 +10202,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>16</real>
|
||||
<integer>16</integer>
|
||||
</map>
|
||||
<key>MeshBytesPerTriangle</key>
|
||||
<map>
|
||||
|
|
@ -10213,7 +10213,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>16</real>
|
||||
<integer>16</integer>
|
||||
</map>
|
||||
<key>Mesh2MaxConcurrentRequests</key>
|
||||
<map>
|
||||
|
|
@ -10345,7 +10345,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>1024</real>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
<key>SceneLoadLowMemoryBound</key>
|
||||
<map>
|
||||
|
|
@ -10356,7 +10356,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>750</real>
|
||||
<integer>750</integer>
|
||||
</map>
|
||||
<key>SceneLoadMinRadius</key>
|
||||
<map>
|
||||
|
|
@ -12149,7 +12149,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>6</real>
|
||||
<integer>6</integer>
|
||||
</map>
|
||||
<key>UICheckboxctrlBtnSize</key>
|
||||
<map>
|
||||
|
|
@ -12160,7 +12160,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>13</real>
|
||||
<integer>13</integer>
|
||||
</map>
|
||||
<key>UICheckboxctrlHeight</key>
|
||||
<map>
|
||||
|
|
@ -12171,7 +12171,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>16</real>
|
||||
<integer>16</integer>
|
||||
</map>
|
||||
<key>UICheckboxctrlHPad</key>
|
||||
<map>
|
||||
|
|
@ -12182,7 +12182,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>2</real>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
<key>UICheckboxctrlSpacing</key>
|
||||
<map>
|
||||
|
|
@ -12193,7 +12193,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>5</real>
|
||||
<integer>5</integer>
|
||||
</map>
|
||||
<key>UICheckboxctrlVPad</key>
|
||||
<map>
|
||||
|
|
@ -12204,7 +12204,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>2</real>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
<key>UICloseBoxFromTop</key>
|
||||
<map>
|
||||
|
|
@ -12215,7 +12215,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>5</real>
|
||||
<integer>5</integer>
|
||||
</map>
|
||||
<key>UIExtraTriangleHeight</key>
|
||||
<map>
|
||||
|
|
@ -12226,7 +12226,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>-1</real>
|
||||
<integer>-1</integer>
|
||||
</map>
|
||||
<key>UIExtraTriangleWidth</key>
|
||||
<map>
|
||||
|
|
@ -12237,7 +12237,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>4</real>
|
||||
<integer>4</integer>
|
||||
</map>
|
||||
<key>UIFloaterCloseBoxSize</key>
|
||||
<map>
|
||||
|
|
@ -12248,7 +12248,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>16</real>
|
||||
<integer>16</integer>
|
||||
</map>
|
||||
<key>UIFloaterHPad</key>
|
||||
<map>
|
||||
|
|
@ -12259,7 +12259,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>6</real>
|
||||
<integer>6</integer>
|
||||
</map>
|
||||
<key>UIFloaterTestBool</key>
|
||||
<map>
|
||||
|
|
@ -12479,7 +12479,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>500</real>
|
||||
<integer>500</integer>
|
||||
</map>
|
||||
<key>UIMinimizedWidth</key>
|
||||
<map>
|
||||
|
|
@ -12490,7 +12490,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>160</real>
|
||||
<integer>160</integer>
|
||||
</map>
|
||||
<key>UIMultiSliderctrlSpacing</key>
|
||||
<map>
|
||||
|
|
@ -12501,7 +12501,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>4</real>
|
||||
<integer>4</integer>
|
||||
</map>
|
||||
<key>UIMultiTrackHeight</key>
|
||||
<map>
|
||||
|
|
@ -13161,7 +13161,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>3</real>
|
||||
<integer>3</integer>
|
||||
</map>
|
||||
<key>UseCircuitCodeTimeout</key>
|
||||
<map>
|
||||
|
|
@ -15169,9 +15169,9 @@
|
|||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</map>
|
||||
|
|
@ -15488,7 +15488,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>2</real>
|
||||
<real>2.0</real>
|
||||
</map>
|
||||
<key>TeleportLocalDelay</key>
|
||||
<map>
|
||||
|
|
@ -15499,7 +15499,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1</real>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>FMODExProfilerEnable</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@
|
|||
// Linden library includes
|
||||
#include "llavatarnamecache.h"
|
||||
#include "lldiriterator.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llmemory.h"
|
||||
#include "llprimitive.h"
|
||||
|
|
@ -4698,6 +4699,32 @@ void LLAppViewer::saveNameCache()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAppViewer::saveExperienceCache()
|
||||
{
|
||||
std::string filename =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml");
|
||||
LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL;
|
||||
llofstream cache_stream(filename.c_str());
|
||||
if(cache_stream.is_open())
|
||||
{
|
||||
LLExperienceCache::exportFile(cache_stream);
|
||||
}
|
||||
}
|
||||
|
||||
void LLAppViewer::loadExperienceCache()
|
||||
{
|
||||
std::string filename =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml");
|
||||
LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL;
|
||||
llifstream cache_stream(filename.c_str());
|
||||
if(cache_stream.is_open())
|
||||
{
|
||||
LLExperienceCache::importFile(cache_stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! @brief This class is an LLFrameTimer that can be created with
|
||||
an elapsed time that starts counting up from the given value
|
||||
rather than 0.0.
|
||||
|
|
@ -4893,7 +4920,7 @@ void LLAppViewer::idle()
|
|||
// floating throughout the various object lists.
|
||||
//
|
||||
idleNameCache();
|
||||
|
||||
idleExperienceCache();
|
||||
idleNetwork();
|
||||
|
||||
|
||||
|
|
@ -5323,6 +5350,22 @@ void LLAppViewer::idleNameCache()
|
|||
LLAvatarNameCache::idle();
|
||||
}
|
||||
|
||||
void LLAppViewer::idleExperienceCache()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region) return;
|
||||
|
||||
std::string lookup_url=region->getCapability("GetExperienceInfo");
|
||||
if(!lookup_url.empty() && *lookup_url.rbegin() != '/')
|
||||
{
|
||||
lookup_url += '/';
|
||||
}
|
||||
|
||||
LLExperienceCache::setLookupURL(lookup_url);
|
||||
|
||||
LLExperienceCache::idle();
|
||||
}
|
||||
|
||||
//
|
||||
// Handle messages, and all message related stuff
|
||||
//
|
||||
|
|
@ -5485,6 +5528,7 @@ void LLAppViewer::disconnectViewer()
|
|||
}
|
||||
|
||||
saveNameCache();
|
||||
saveExperienceCache();
|
||||
|
||||
// close inventory interface, close all windows
|
||||
LLFloaterInventory::cleanup();
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@ public:
|
|||
void loadNameCache();
|
||||
void saveNameCache();
|
||||
|
||||
void loadExperienceCache();
|
||||
void saveExperienceCache();
|
||||
|
||||
void removeMarkerFiles();
|
||||
|
||||
void removeDumpDir();
|
||||
|
|
@ -230,6 +233,7 @@ private:
|
|||
void idle();
|
||||
void idleShutdown();
|
||||
// update avatar SLID and display name caches
|
||||
void idleExperienceCache();
|
||||
void idleNameCache();
|
||||
void idleNetwork();
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ void LLAssetUploadQueue::request(LLAssetUploadQueueSupplier** supplier)
|
|||
body["item_id"] = data.mItemId;
|
||||
body["is_script_running"] = data.mIsRunning;
|
||||
body["target"] = data.mIsTargetMono? "mono" : "lsl2";
|
||||
body["experience"] = data.mExperienceId;
|
||||
|
||||
std::string url = "";
|
||||
LLViewerObject* object = gObjectList.findObject(data.mTaskId);
|
||||
|
|
@ -191,7 +192,8 @@ void LLAssetUploadQueue::queue(const std::string& filename,
|
|||
const LLUUID& queue_id,
|
||||
U8* script_data,
|
||||
U32 data_size,
|
||||
std::string script_name)
|
||||
std::string script_name,
|
||||
const LLUUID& experience_id)
|
||||
{
|
||||
UploadData data;
|
||||
data.mTaskId = task_id;
|
||||
|
|
@ -203,6 +205,7 @@ void LLAssetUploadQueue::queue(const std::string& filename,
|
|||
data.mData = script_data;
|
||||
data.mDataSize = data_size;
|
||||
data.mScriptName = script_name;
|
||||
data.mExperienceId = experience_id;
|
||||
|
||||
mQueue.push_back(data);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ public:
|
|||
const LLUUID& queue_id,
|
||||
U8* data,
|
||||
U32 data_size,
|
||||
std::string script_name);
|
||||
std::string script_name,
|
||||
const LLUUID& experience_id);
|
||||
|
||||
bool isEmpty() const {return mQueue.empty();}
|
||||
|
||||
|
|
@ -69,6 +70,7 @@ private:
|
|||
U8* mData;
|
||||
U32 mDataSize;
|
||||
std::string mScriptName;
|
||||
LLUUID mExperienceId;
|
||||
};
|
||||
|
||||
// Ownership of mSupplier passed to currently waiting responder
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@
|
|||
#include "lltrans.h"
|
||||
|
||||
#include "llselectmgr.h"
|
||||
#include "llexperienceassociationresponder.h"
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
// *TODO: This should be separated into the script queue, and the floater views of that queue.
|
||||
// There should only be one floater class that can view any queue type
|
||||
|
|
@ -70,11 +72,13 @@
|
|||
struct LLScriptQueueData
|
||||
{
|
||||
LLUUID mQueueID;
|
||||
std::string mScriptName;
|
||||
LLUUID mTaskId;
|
||||
LLUUID mItemId;
|
||||
LLScriptQueueData(const LLUUID& q_id, const std::string& name, const LLUUID& task_id, const LLUUID& item_id) :
|
||||
mQueueID(q_id), mScriptName(name), mTaskId(task_id), mItemId(item_id) {}
|
||||
LLPointer<LLInventoryItem> mItem;
|
||||
LLHost mHost;
|
||||
LLUUID mExperienceId;
|
||||
std::string mExperiencename;
|
||||
LLScriptQueueData(const LLUUID& q_id, const LLUUID& task_id, LLInventoryItem* item) :
|
||||
mQueueID(q_id), mTaskId(task_id), mItem(new LLInventoryItem(item)) {}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -88,6 +92,7 @@ LLFloaterScriptQueue::LLFloaterScriptQueue(const LLSD& key) :
|
|||
mDone(false),
|
||||
mMono(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Destroys the object
|
||||
|
|
@ -167,7 +172,7 @@ BOOL LLFloaterScriptQueue::start()
|
|||
|
||||
getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
|
||||
|
||||
return nextObject();
|
||||
return startQueue();
|
||||
}
|
||||
|
||||
BOOL LLFloaterScriptQueue::isDone() const
|
||||
|
|
@ -232,6 +237,40 @@ BOOL LLFloaterScriptQueue::popNext()
|
|||
return rv;
|
||||
}
|
||||
|
||||
BOOL LLFloaterScriptQueue::startQueue()
|
||||
{
|
||||
return nextObject();
|
||||
}
|
||||
|
||||
class CompileQueueExperienceResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
CompileQueueExperienceResponder(const LLUUID& parent):mParent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
LLUUID mParent;
|
||||
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
sendResult(getContent());
|
||||
}
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
sendResult(LLSD());
|
||||
}
|
||||
void sendResult(const LLSD& content)
|
||||
{
|
||||
LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", mParent);
|
||||
if(!queue)
|
||||
return;
|
||||
|
||||
queue->experienceIdsReceived(content["experience_ids"]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLFloaterCompileQueue
|
||||
|
|
@ -284,6 +323,21 @@ LLFloaterCompileQueue::~LLFloaterCompileQueue()
|
|||
{
|
||||
}
|
||||
|
||||
void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content )
|
||||
{
|
||||
for(LLSD::array_const_iterator it = content.beginArray(); it != content.endArray(); ++it)
|
||||
{
|
||||
mExperienceIds.insert(it->asUUID());
|
||||
}
|
||||
nextObject();
|
||||
}
|
||||
|
||||
BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
|
||||
{
|
||||
return mExperienceIds.find(id) != mExperienceIds.end();
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
|
||||
LLInventoryObject::object_list_t* inv)
|
||||
{
|
||||
|
|
@ -324,25 +378,52 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
|
|||
{
|
||||
LLInventoryItem *itemp = iter->second;
|
||||
LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(),
|
||||
itemp->getName(),
|
||||
viewer_object->getID(),
|
||||
itemp->getUUID());
|
||||
viewer_object->getID(), itemp);
|
||||
|
||||
//LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL;
|
||||
gAssetStorage->getInvItemAsset(viewer_object->getRegion()->getHost(),
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
itemp->getPermissions().getOwner(),
|
||||
viewer_object->getID(),
|
||||
itemp->getUUID(),
|
||||
itemp->getAssetUUID(),
|
||||
itemp->getType(),
|
||||
LLFloaterCompileQueue::scriptArrived,
|
||||
(void*)datap);
|
||||
ExperienceAssociationResponder::fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
|
||||
boost::bind(LLFloaterCompileQueue::requestAsset, datap, _1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterCompileQueue::requestAsset( LLScriptQueueData* datap, const LLSD& experience )
|
||||
{
|
||||
LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", datap->mQueueID);
|
||||
if(!queue)
|
||||
{
|
||||
delete datap;
|
||||
return;
|
||||
}
|
||||
if(experience.has(LLExperienceCache::EXPERIENCE_ID))
|
||||
{
|
||||
datap->mExperienceId=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
if(!queue->hasExperience(datap->mExperienceId))
|
||||
{
|
||||
std::string buffer = LLTrans::getString("CompileNoExperiencePerm", LLSD::emptyMap()
|
||||
.with("SCRIPT", datap->mItem->getName())
|
||||
.with("EXPERIENCE", experience[LLExperienceCache::NAME].asString()));
|
||||
|
||||
queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
|
||||
queue->removeItemByItemID(datap->mItem->getUUID());
|
||||
delete datap;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL;
|
||||
gAssetStorage->getInvItemAsset(datap->mHost,
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
datap->mItem->getPermissions().getOwner(),
|
||||
datap->mTaskId,
|
||||
datap->mItem->getUUID(),
|
||||
datap->mItem->getAssetUUID(),
|
||||
datap->mItem->getType(),
|
||||
LLFloaterCompileQueue::scriptArrived,
|
||||
(void*)datap);
|
||||
}
|
||||
|
||||
|
||||
// This is the callback for when each script arrives
|
||||
// static
|
||||
void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
|
|
@ -382,12 +463,12 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
|||
file.read(script_data, script_size);
|
||||
|
||||
queue->mUploadQueue->queue(filename, data->mTaskId,
|
||||
data->mItemId, is_running, queue->mMono, queue->getKey().asUUID(),
|
||||
script_data, script_size, data->mScriptName);
|
||||
data->mItem->getUUID(), is_running, queue->mMono, queue->getKey().asUUID(),
|
||||
script_data, script_size, data->mItem->getName(), data->mExperienceId);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = LLTrans::getString("CompileQueueServiceUnavailable") + (": ") + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueServiceUnavailable") + (": ") + data->mItem->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -399,7 +480,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
|||
args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound");
|
||||
LLNotificationsUtil::add("SystemMessage", args);
|
||||
|
||||
buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mItem->getName();
|
||||
}
|
||||
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
|
||||
{
|
||||
|
|
@ -407,15 +488,15 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
|||
args["MESSAGE"] = LLTrans::getString("CompileQueueInsufficientPermDownload");
|
||||
LLNotificationsUtil::add("SystemMessage", args);
|
||||
|
||||
buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mItem->getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mItem->getName();
|
||||
}
|
||||
|
||||
LL_WARNS() << "Problem downloading script asset." << LL_ENDL;
|
||||
if(queue) queue->removeItemByItemID(data->mItemId);
|
||||
if(queue) queue->removeItemByItemID(data->mItem->getUUID());
|
||||
}
|
||||
if(queue && (buffer.size() > 0))
|
||||
{
|
||||
|
|
@ -564,6 +645,23 @@ void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id)
|
|||
}
|
||||
}
|
||||
|
||||
BOOL LLFloaterCompileQueue::startQueue()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
std::string lookup_url=region->getCapability("GetCreatorExperiences");
|
||||
if(!lookup_url.empty())
|
||||
{
|
||||
LLHTTPClient::get(lookup_url, new CompileQueueExperienceResponder(getKey().asUUID()));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return nextObject();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
|
||||
LLInventoryObject::object_list_t* inv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -81,13 +81,15 @@ protected:
|
|||
// returns true if this is done
|
||||
BOOL isDone() const;
|
||||
|
||||
virtual BOOL startQueue();
|
||||
|
||||
// go to the next object. If no objects left, it falls out
|
||||
// silently and waits to be killed by the deleteIfDone() callback.
|
||||
BOOL nextObject();
|
||||
BOOL popNext();
|
||||
|
||||
void setStartString(const std::string& s) { mStartString = s; }
|
||||
|
||||
|
||||
protected:
|
||||
// UI
|
||||
LLScrollListCtrl* mMessages;
|
||||
|
|
@ -131,6 +133,9 @@ public:
|
|||
|
||||
LLAssetUploadQueue* getUploadQueue() { return mUploadQueue; }
|
||||
|
||||
void experienceIdsReceived( const LLSD& content );
|
||||
BOOL hasExperience(const LLUUID& id)const;
|
||||
|
||||
protected:
|
||||
LLFloaterCompileQueue(const LLSD& key);
|
||||
virtual ~LLFloaterCompileQueue();
|
||||
|
|
@ -139,16 +144,21 @@ protected:
|
|||
virtual void handleInventory(LLViewerObject* viewer_obj,
|
||||
LLInventoryObject::object_list_t* inv);
|
||||
|
||||
static void requestAsset(struct LLScriptQueueData* datap, const LLSD& experience);
|
||||
|
||||
|
||||
// This is the callback for when each script arrives
|
||||
static void scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
LLAssetType::EType type,
|
||||
void* user_data, S32 status, LLExtStat ext_status);
|
||||
|
||||
virtual BOOL startQueue();
|
||||
protected:
|
||||
LLViewerInventoryItem::item_array_t mCurrentScripts;
|
||||
|
||||
private:
|
||||
LLAssetUploadQueue* mUploadQueue;
|
||||
uuid_list_t mExperienceIds;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p)
|
|||
mExpanderVisible(false)
|
||||
{
|
||||
setIsChrome(TRUE);
|
||||
|
||||
setMaxTextLength(p.max_text_length);
|
||||
}
|
||||
|
||||
void LLExpandableTextBox::LLTextBoxEx::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public:
|
|||
Optional<LLScrollContainer::Params> scroll;
|
||||
|
||||
Optional<S32> max_height;
|
||||
|
||||
|
||||
Optional<bool> bg_visible,
|
||||
expanded_bg_visible;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* @file llexperienceassociationresponder.cpp
|
||||
* @brief llexperienceassociationresponder implementation. This class combines
|
||||
* a lookup for a script association and an experience details request. The first
|
||||
* is always async, but the second may be cached locally.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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 "llexperienceassociationresponder.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llagent.h"
|
||||
|
||||
ExperienceAssociationResponder::ExperienceAssociationResponder(ExperienceAssociationResponder::callback_t callback):mCallback(callback)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
void ExperienceAssociationResponder::fetchAssociatedExperience( const LLUUID& object_id, const LLUUID& item_id, callback_t callback )
|
||||
{
|
||||
LLSD request;
|
||||
request["object-id"]=object_id;
|
||||
request["item-id"]=item_id;
|
||||
fetchAssociatedExperience(request, callback);
|
||||
}
|
||||
|
||||
void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, callback_t callback)
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
std::string lookup_url=region->getCapability("GetMetadata");
|
||||
if(!lookup_url.empty())
|
||||
{
|
||||
LLSD fields;
|
||||
fields.append("experience");
|
||||
request["fields"] = fields;
|
||||
LLHTTPClient::post(lookup_url, request, new ExperienceAssociationResponder(callback));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExperienceAssociationResponder::httpFailure()
|
||||
{
|
||||
LLSD msg;
|
||||
msg["error"]=(LLSD::Integer)getStatus();
|
||||
msg["message"]=getReason();
|
||||
LL_INFOS("ExperienceAssociation") << "Failed to look up associated experience: " << getStatus() << ": " << getReason() << LL_ENDL;
|
||||
|
||||
sendResult(msg);
|
||||
|
||||
}
|
||||
void ExperienceAssociationResponder::httpSuccess()
|
||||
{
|
||||
if(!getContent().has("experience"))
|
||||
{
|
||||
|
||||
LLSD msg;
|
||||
msg["message"]="no experience";
|
||||
msg["error"]=-1;
|
||||
sendResult(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
LLExperienceCache::get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1));
|
||||
|
||||
}
|
||||
|
||||
void ExperienceAssociationResponder::sendResult( const LLSD& experience )
|
||||
{
|
||||
mCallback(experience);
|
||||
unref();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#include "llhttpclient.h"
|
||||
#include "llsd.h"
|
||||
/**
|
||||
* @file llexperienceassociationresponder.h
|
||||
* @brief llexperienceassociationresponder and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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_LLEXPERIENCEASSOCIATIONRESPONDER_H
|
||||
#define LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
|
||||
|
||||
#include "llhttpclient.h"
|
||||
#include "llsd.h"
|
||||
|
||||
class ExperienceAssociationResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void(const LLSD& experience)> callback_t;
|
||||
|
||||
ExperienceAssociationResponder(callback_t callback);
|
||||
|
||||
/*virtual*/ void httpSuccess();
|
||||
/*virtual*/ void httpFailure();
|
||||
|
||||
static void fetchAssociatedExperience(const LLUUID& object_it, const LLUUID& item_id, callback_t callback);
|
||||
|
||||
private:
|
||||
static void fetchAssociatedExperience(LLSD& request, callback_t callback);
|
||||
|
||||
void sendResult(const LLSD& experience);
|
||||
|
||||
callback_t mCallback;
|
||||
|
||||
};
|
||||
|
||||
#endif // LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
* @file llexperiencelog.cpp
|
||||
* @brief llexperiencelog implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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 "llexperiencelog.h"
|
||||
|
||||
#include "lldispatcher.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llviewergenericmessage.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "lltrans.h"
|
||||
#include "llerror.h"
|
||||
#include "lldate.h"
|
||||
|
||||
|
||||
class LLExperienceLogDispatchHandler : public LLDispatchHandler
|
||||
{
|
||||
public:
|
||||
virtual bool operator()(
|
||||
const LLDispatcher* dispatcher,
|
||||
const std::string& key,
|
||||
const LLUUID& invoice,
|
||||
const sparam_t& strings)
|
||||
{
|
||||
LLSD message;
|
||||
|
||||
sparam_t::const_iterator it = strings.begin();
|
||||
if(it != strings.end()){
|
||||
const std::string& llsdRaw = *it++;
|
||||
std::istringstream llsdData(llsdRaw);
|
||||
if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
|
||||
{
|
||||
LL_WARNS() << "LLExperienceLogDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
|
||||
}
|
||||
}
|
||||
message["public_id"] = invoice;
|
||||
|
||||
// Object Name
|
||||
if(it != strings.end())
|
||||
{
|
||||
message["ObjectName"] = *it++;
|
||||
}
|
||||
|
||||
// parcel Name
|
||||
if(it != strings.end())
|
||||
{
|
||||
message["ParcelName"] = *it++;
|
||||
}
|
||||
message["Count"] = 1;
|
||||
|
||||
LLExperienceLog::instance().handleExperienceMessage(message);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static LLExperienceLogDispatchHandler experience_log_dispatch_handler;
|
||||
|
||||
void LLExperienceLog::handleExperienceMessage(LLSD& message)
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
char daybuf[16];/* Flawfinder: ignore */
|
||||
char time_of_day[16];/* Flawfinder: ignore */
|
||||
strftime(daybuf, 16, "%Y-%m-%d", localtime(&now));
|
||||
strftime(time_of_day, 16, " %H:%M:%S", localtime(&now));
|
||||
message["Time"] = time_of_day;
|
||||
|
||||
std::string day = daybuf;
|
||||
|
||||
if(!mEvents.has(day))
|
||||
{
|
||||
mEvents[day] = LLSD::emptyArray();
|
||||
}
|
||||
LLSD& dayEvents = mEvents[day];
|
||||
if(dayEvents.size() > 0)
|
||||
{
|
||||
LLSD& last = *(dayEvents.rbeginArray());
|
||||
if( last["public_id"].asUUID() == message["public_id"].asUUID()
|
||||
&& last["ObjectName"].asString() == message["ObjectName"].asString()
|
||||
&& last["OwnerID"].asUUID() == message["OwnerID"].asUUID()
|
||||
&& last["ParcelName"].asString() == message["ParcelName"].asString()
|
||||
&& last["Permission"].asInteger() == message["Permission"].asInteger())
|
||||
{
|
||||
last["Count"] = last["Count"].asInteger() + 1;
|
||||
last["Time"] = time_of_day;
|
||||
mSignals(last);
|
||||
return;
|
||||
}
|
||||
}
|
||||
message["Time"] = time_of_day;
|
||||
mEvents[day].append(message);
|
||||
mSignals(message);
|
||||
}
|
||||
|
||||
LLExperienceLog::LLExperienceLog()
|
||||
: mMaxDays(7)
|
||||
, mPageSize(25)
|
||||
, mNotifyNewEvent(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLExperienceLog::initialize()
|
||||
{
|
||||
loadEvents();
|
||||
if(!gGenericDispatcher.isHandlerPresent("ExperienceEvent"))
|
||||
{
|
||||
gGenericDispatcher.addHandler("ExperienceEvent", &experience_log_dispatch_handler);
|
||||
}
|
||||
}
|
||||
|
||||
std::string LLExperienceLog::getFilename()
|
||||
{
|
||||
return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "experience_events.xml");
|
||||
}
|
||||
|
||||
|
||||
std::string LLExperienceLog::getPermissionString( const LLSD& message, const std::string& base )
|
||||
{
|
||||
std::ostringstream buf;
|
||||
if(message.has("Permission"))
|
||||
{
|
||||
buf << base << message["Permission"].asInteger();
|
||||
std::string entry;
|
||||
if(LLTrans::findString(entry, buf.str()))
|
||||
{
|
||||
buf.str(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.str();
|
||||
}
|
||||
}
|
||||
|
||||
if(buf.str().empty())
|
||||
{
|
||||
buf << base << "Unknown";
|
||||
|
||||
buf.str(LLTrans::getString(buf.str(), message));
|
||||
}
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
void LLExperienceLog::notify( LLSD& message )
|
||||
{
|
||||
message["EventType"] = getPermissionString(message, "ExperiencePermission");
|
||||
if(message.has("IsAttachment") && message["IsAttachment"].asBoolean())
|
||||
{
|
||||
LLNotificationsUtil::add("ExperienceEventAttachment", message);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("ExperienceEvent", message);
|
||||
}
|
||||
message.erase("EventType");
|
||||
}
|
||||
|
||||
void LLExperienceLog::saveEvents()
|
||||
{
|
||||
eraseExpired();
|
||||
std::string filename = getFilename();
|
||||
LLSD settings = LLSD::emptyMap().with("Events", mEvents);
|
||||
|
||||
settings["MaxDays"] = (int)mMaxDays;
|
||||
settings["Notify"] = mNotifyNewEvent;
|
||||
settings["PageSize"] = (int)mPageSize;
|
||||
|
||||
llofstream stream(filename.c_str());
|
||||
LLSDSerialize::toPrettyXML(settings, stream);
|
||||
}
|
||||
|
||||
|
||||
void LLExperienceLog::loadEvents()
|
||||
{
|
||||
LLSD settings = LLSD::emptyMap();
|
||||
|
||||
std::string filename = getFilename();
|
||||
llifstream stream(filename.c_str());
|
||||
LLSDSerialize::fromXMLDocument(settings, stream);
|
||||
|
||||
if(settings.has("MaxDays"))
|
||||
{
|
||||
setMaxDays((U32)settings["MaxDays"].asInteger());
|
||||
}
|
||||
if(settings.has("Notify"))
|
||||
{
|
||||
setNotifyNewEvent(settings["Notify"].asBoolean());
|
||||
}
|
||||
if(settings.has("PageSize"))
|
||||
{
|
||||
setPageSize((U32)settings["PageSize"].asInteger());
|
||||
}
|
||||
mEvents.clear();
|
||||
if(mMaxDays > 0 && settings.has("Events"))
|
||||
{
|
||||
mEvents = settings["Events"];
|
||||
}
|
||||
|
||||
eraseExpired();
|
||||
}
|
||||
|
||||
LLExperienceLog::~LLExperienceLog()
|
||||
{
|
||||
saveEvents();
|
||||
}
|
||||
|
||||
void LLExperienceLog::eraseExpired()
|
||||
{
|
||||
while(mEvents.size() > mMaxDays && mMaxDays > 0)
|
||||
{
|
||||
mEvents.erase(mEvents.beginMap()->first);
|
||||
}
|
||||
}
|
||||
|
||||
const LLSD& LLExperienceLog::getEvents() const
|
||||
{
|
||||
return mEvents;
|
||||
}
|
||||
|
||||
void LLExperienceLog::clear()
|
||||
{
|
||||
mEvents.clear();
|
||||
}
|
||||
|
||||
void LLExperienceLog::setMaxDays( U32 val )
|
||||
{
|
||||
mMaxDays = val;
|
||||
if(mMaxDays > 0)
|
||||
{
|
||||
eraseExpired();
|
||||
}
|
||||
}
|
||||
|
||||
LLExperienceLog::callback_connection_t LLExperienceLog::addUpdateSignal( const callback_slot_t& cb )
|
||||
{
|
||||
return mSignals.connect(cb);
|
||||
}
|
||||
|
||||
void LLExperienceLog::setNotifyNewEvent( bool val )
|
||||
{
|
||||
mNotifyNewEvent = val;
|
||||
if(!val && mNotifyConnection.connected())
|
||||
{
|
||||
mNotifyConnection.disconnect();
|
||||
}
|
||||
else if( val && !mNotifyConnection.connected())
|
||||
{
|
||||
mNotifyConnection = addUpdateSignal(boost::function<void(LLSD&)>(LLExperienceLog::notify));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @file llexperiencelog.h
|
||||
* @brief llexperiencelog and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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_LLEXPERIENCELOG_H
|
||||
#define LL_LLEXPERIENCELOG_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
|
||||
class LLExperienceLog : public LLSingleton<LLExperienceLog>
|
||||
{
|
||||
public:
|
||||
typedef boost::signals2::signal<void(LLSD&)>
|
||||
callback_signal_t;
|
||||
typedef callback_signal_t::slot_type callback_slot_t;
|
||||
typedef boost::signals2::connection callback_connection_t;
|
||||
callback_connection_t addUpdateSignal(const callback_slot_t& cb);
|
||||
|
||||
void initialize();
|
||||
|
||||
U32 getMaxDays() const { return mMaxDays; }
|
||||
void setMaxDays(U32 val);
|
||||
|
||||
bool getNotifyNewEvent() const { return mNotifyNewEvent; }
|
||||
void setNotifyNewEvent(bool val);
|
||||
|
||||
U32 getPageSize() const { return mPageSize; }
|
||||
void setPageSize(U32 val) { mPageSize = val; }
|
||||
|
||||
const LLSD& getEvents()const;
|
||||
void clear();
|
||||
|
||||
virtual ~LLExperienceLog();
|
||||
|
||||
static void notify(LLSD& message);
|
||||
static std::string getFilename();
|
||||
static std::string getPermissionString(const LLSD& message, const std::string& base);
|
||||
protected:
|
||||
LLExperienceLog();
|
||||
void handleExperienceMessage(LLSD& message);
|
||||
|
||||
|
||||
void loadEvents();
|
||||
void saveEvents();
|
||||
void eraseExpired();
|
||||
|
||||
LLSD mEvents;
|
||||
callback_signal_t mSignals;
|
||||
callback_connection_t mNotifyConnection;
|
||||
U32 mMaxDays;
|
||||
U32 mPageSize;
|
||||
bool mNotifyNewEvent;
|
||||
|
||||
friend class LLExperienceLogDispatchHandler;
|
||||
friend class LLSingleton<LLExperienceLog>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // LL_LLEXPERIENCELOG_H
|
||||
|
|
@ -380,13 +380,16 @@ void LLFloaterAuction::doResetParcel()
|
|||
msg->sendReliable(region->getHost());
|
||||
|
||||
// Clear the access lists
|
||||
clearParcelAccessLists(parcelp, region);
|
||||
clearParcelAccessList(parcelp, region, AL_ACCESS);
|
||||
clearParcelAccessList(parcelp, region, AL_BAN);
|
||||
clearParcelAccessList(parcelp, region, AL_ALLOW_EXPERIENCE);
|
||||
clearParcelAccessList(parcelp, region, AL_BLOCK_EXPERIENCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion* region)
|
||||
void LLFloaterAuction::clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list)
|
||||
{
|
||||
if (!region || !parcel) return;
|
||||
|
||||
|
|
@ -395,15 +398,12 @@ void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion*
|
|||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
// Clear access list
|
||||
// parcel->mAccessList.clear();
|
||||
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
|
||||
msg->addU32Fast(_PREHASH_Flags, list);
|
||||
msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
|
||||
msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
|
||||
|
|
@ -416,27 +416,6 @@ void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion*
|
|||
msg->addU32Fast(_PREHASH_Flags, 0 );
|
||||
|
||||
msg->sendReliable( region->getHost() );
|
||||
|
||||
// Send message for empty ban list
|
||||
//parcel->mBanList.clear();
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addU32Fast(_PREHASH_Flags, AL_BAN);
|
||||
msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
|
||||
msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
|
||||
msg->addS32Fast(_PREHASH_Sections, 0); // num_sections
|
||||
|
||||
// pack an empty block since there will be no data
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
|
||||
msg->addS32Fast(_PREHASH_Time, 0 );
|
||||
msg->addU32Fast(_PREHASH_Flags, 0 );
|
||||
|
||||
msg->sendReliable( region->getHost() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ private:
|
|||
|
||||
void doResetParcel();
|
||||
void doSellToAnyone();
|
||||
void clearParcelAccessLists( LLParcel* parcel, LLViewerRegion* region );
|
||||
void clearParcelAccessList( LLParcel* parcel, LLViewerRegion* region, U32 list);
|
||||
void cleanupAndClose();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* @file llfloaterexperiencepicker.cpp
|
||||
* @brief Implementation of llfloaterexperiencepicker
|
||||
* @author dolphin@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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 "llfloaterexperiencepicker.h"
|
||||
|
||||
|
||||
#include "lllineeditor.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llagent.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llslurl.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "lldraghandle.h"
|
||||
#include "llpanelexperiencepicker.h"
|
||||
|
||||
LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin )
|
||||
{
|
||||
LLFloaterExperiencePicker* floater =
|
||||
LLFloaterReg::showTypedInstance<LLFloaterExperiencePicker>("experience_search", key);
|
||||
if (!floater)
|
||||
{
|
||||
LL_WARNS() << "Cannot instantiate experience picker" << LL_ENDL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (floater->mSearchPanel)
|
||||
{
|
||||
floater->mSearchPanel->mSelectionCallback = callback;
|
||||
floater->mSearchPanel->mCloseOnSelect = close_on_select;
|
||||
floater->mSearchPanel->setAllowMultiple(allow_multiple);
|
||||
floater->mSearchPanel->setDefaultFilters();
|
||||
floater->mSearchPanel->addFilters(filters.begin(), filters.end());
|
||||
floater->mSearchPanel->filterContent();
|
||||
}
|
||||
|
||||
if(frustumOrigin)
|
||||
{
|
||||
floater->mFrustumOrigin = frustumOrigin->getHandle();
|
||||
}
|
||||
|
||||
return floater;
|
||||
}
|
||||
|
||||
void LLFloaterExperiencePicker::drawFrustum()
|
||||
{
|
||||
if(mFrustumOrigin.get())
|
||||
{
|
||||
LLView * frustumOrigin = mFrustumOrigin.get();
|
||||
LLRect origin_rect;
|
||||
frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
|
||||
// draw context cone connecting color picker with color swatch in parent floater
|
||||
LLRect local_rect = getLocalRect();
|
||||
if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
LLGLEnable(GL_CULL_FACE);
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
|
||||
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
|
||||
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
|
||||
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
|
||||
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
|
||||
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
|
||||
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
|
||||
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
if (gFocusMgr.childHasMouseCapture(getDragHandle()))
|
||||
{
|
||||
mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiencePicker::draw()
|
||||
{
|
||||
drawFrustum();
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
||||
LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key )
|
||||
:LLFloater(key)
|
||||
,mSearchPanel(NULL)
|
||||
,mContextConeOpacity(0.f)
|
||||
,mContextConeInAlpha(0.f)
|
||||
,mContextConeOutAlpha(0.f)
|
||||
,mContextConeFadeTime(0.f)
|
||||
{
|
||||
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
|
||||
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
|
||||
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
|
||||
}
|
||||
|
||||
LLFloaterExperiencePicker::~LLFloaterExperiencePicker()
|
||||
{
|
||||
gFocusMgr.releaseFocusIfNeeded( this );
|
||||
}
|
||||
|
||||
BOOL LLFloaterExperiencePicker::postBuild()
|
||||
{
|
||||
mSearchPanel = new LLPanelExperiencePicker();
|
||||
addChild(mSearchPanel);
|
||||
mSearchPanel->setOrigin(0, 0);
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* @file llfloaterexperiencepicker.h
|
||||
* @brief Header file for llfloaterexperiencepicker
|
||||
* @author dolphin@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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_LLFLOATEREXPERIENCEPICKER_H
|
||||
#define LL_LLFLOATEREXPERIENCEPICKER_H
|
||||
|
||||
#include "llfloater.h"
|
||||
|
||||
class LLScrollListCtrl;
|
||||
class LLLineEditor;
|
||||
class LLPanelExperiencePicker;
|
||||
|
||||
|
||||
class LLFloaterExperiencePicker : public LLFloater
|
||||
{
|
||||
public:
|
||||
|
||||
typedef boost::function<void (const uuid_vec_t&)> select_callback_t;
|
||||
// filter function for experiences, return true if the experience should be hidden.
|
||||
typedef boost::function<bool (const LLSD&)> filter_function;
|
||||
typedef std::vector<filter_function> filter_list;
|
||||
|
||||
static LLFloaterExperiencePicker* show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin);
|
||||
|
||||
LLFloaterExperiencePicker(const LLSD& key);
|
||||
virtual ~LLFloaterExperiencePicker();
|
||||
|
||||
BOOL postBuild();
|
||||
|
||||
virtual void draw();
|
||||
private:
|
||||
|
||||
LLPanelExperiencePicker* mSearchPanel;
|
||||
|
||||
void drawFrustum();
|
||||
LLHandle <LLView> mFrustumOrigin;
|
||||
F32 mContextConeOpacity;
|
||||
F32 mContextConeInAlpha;
|
||||
F32 mContextConeOutAlpha;
|
||||
F32 mContextConeFadeTime;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATEREXPERIENCEPICKER_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* @file llfloaterexperienceprofile.h
|
||||
* @brief llfloaterexperienceprofile and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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_LLFLOATEREXPERIENCEPROFILE_H
|
||||
#define LL_LLFLOATEREXPERIENCEPROFILE_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lluuid.h"
|
||||
#include "llsd.h"
|
||||
|
||||
class LLLayoutPanel;
|
||||
class LLTextBox;
|
||||
class LLComboBox;
|
||||
|
||||
class LLFloaterExperienceProfile : public LLFloater
|
||||
{
|
||||
LOG_CLASS(LLFloaterExperienceProfile);
|
||||
public:
|
||||
enum PostSaveAction
|
||||
{
|
||||
NOTHING,
|
||||
CLOSE,
|
||||
VIEW,
|
||||
};
|
||||
|
||||
|
||||
LLFloaterExperienceProfile(const LLSD& data);
|
||||
virtual ~LLFloaterExperienceProfile();
|
||||
|
||||
LLUUID getExperienceId() const { return mExperienceId; }
|
||||
void setPreferences( const LLSD& content );
|
||||
|
||||
|
||||
void refreshExperience(const LLSD& experience);
|
||||
void onSaveComplete( const LLSD& content );
|
||||
virtual BOOL canClose();
|
||||
|
||||
virtual void onClose(bool app_quitting);
|
||||
protected:
|
||||
void onClickEdit();
|
||||
void onClickPermission(const char* permission);
|
||||
void onClickForget();
|
||||
void onClickCancel();
|
||||
void onClickSave();
|
||||
void onClickLocation();
|
||||
void onClickClear();
|
||||
void onPickGroup();
|
||||
void onFieldChanged();
|
||||
void onReportExperience();
|
||||
|
||||
void setEditGroup(LLUUID group_id);
|
||||
|
||||
void changeToView();
|
||||
|
||||
void experienceForgotten();
|
||||
void experienceBlocked();
|
||||
void experienceAllowed();
|
||||
|
||||
static void experienceCallback(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& experience);
|
||||
static bool experiencePermission(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& permission);
|
||||
|
||||
BOOL postBuild();
|
||||
bool setMaturityString(U8 maturity, LLTextBox* child, LLComboBox* combo);
|
||||
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response, PostSaveAction action);
|
||||
void doSave( int success_action );
|
||||
|
||||
void updatePackage();
|
||||
|
||||
void updatePermission( const LLSD& permission );
|
||||
LLUUID mExperienceId;
|
||||
LLSD mExperienceDetails;
|
||||
LLSD mPackage;
|
||||
std::string mLocationSLURL;
|
||||
int mSaveCompleteAction;
|
||||
bool mDirty;
|
||||
bool mForceClose;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATEREXPERIENCEPROFILE_H
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
/**
|
||||
* @file llfloaterexperiences.cpp
|
||||
* @brief LLFloaterExperiences class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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 "llfloaterexperiences.h"
|
||||
#include "llfloaterreg.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llevents.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llfloaterregioninfo.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llpanelexperiencelog.h"
|
||||
#include "llpanelexperiencepicker.h"
|
||||
#include "llpanelexperiences.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
|
||||
#define SHOW_RECENT_TAB (0)
|
||||
|
||||
class LLExperienceListResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, std::string> NameMap;
|
||||
typedef boost::function<void(LLPanelExperiences*, const LLSD&)> Callback;
|
||||
LLExperienceListResponder(const LLHandle<LLFloaterExperiences>& parent, NameMap& nameMap, const std::string& errorMessage="ErrorMessage"):mParent(parent),mErrorMessage(errorMessage)
|
||||
{
|
||||
mNameMap.swap(nameMap);
|
||||
}
|
||||
|
||||
Callback mCallback;
|
||||
LLHandle<LLFloaterExperiences> mParent;
|
||||
NameMap mNameMap;
|
||||
const std::string mErrorMessage;
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
if(mParent.isDead())
|
||||
return;
|
||||
|
||||
LLFloaterExperiences* parent=mParent.get();
|
||||
LLTabContainer* tabs = parent->getChild<LLTabContainer>("xp_tabs");
|
||||
|
||||
NameMap::iterator it = mNameMap.begin();
|
||||
while(it != mNameMap.end())
|
||||
{
|
||||
if(getContent().has(it->first))
|
||||
{
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName(it->second);
|
||||
if(tab)
|
||||
{
|
||||
const LLSD& ids = getContent()[it->first];
|
||||
tab->setExperienceList(ids);
|
||||
if(!mCallback.empty())
|
||||
{
|
||||
mCallback(tab, getContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
LLSD subs;
|
||||
subs["ERROR_MESSAGE"] = getReason();
|
||||
LLNotificationsUtil::add(mErrorMessage, subs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LLFloaterExperiences::LLFloaterExperiences(const LLSD& data)
|
||||
:LLFloater(data)
|
||||
{
|
||||
}
|
||||
|
||||
LLPanelExperiences* LLFloaterExperiences::addTab(const std::string& name, bool select)
|
||||
{
|
||||
LLPanelExperiences* newPanel = LLPanelExperiences::create(name);
|
||||
getChild<LLTabContainer>("xp_tabs")->addTabPanel(LLTabContainer::TabPanelParams().
|
||||
panel(newPanel).
|
||||
label(LLTrans::getString(name)).
|
||||
select_tab(select));
|
||||
|
||||
return newPanel;
|
||||
}
|
||||
|
||||
BOOL LLFloaterExperiences::postBuild()
|
||||
{
|
||||
getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperiencePicker());
|
||||
addTab("Allowed_Experiences_Tab", true);
|
||||
addTab("Blocked_Experiences_Tab", false);
|
||||
addTab("Admin_Experiences_Tab", false);
|
||||
addTab("Contrib_Experiences_Tab", false);
|
||||
LLPanelExperiences* owned = addTab("Owned_Experiences_Tab", false);
|
||||
owned->setButtonAction("acquire", boost::bind(&LLFloaterExperiences::sendPurchaseRequest, this));
|
||||
owned->enableButton(false);
|
||||
#if SHOW_RECENT_TAB
|
||||
addTab("Recent_Experiences_Tab", false);
|
||||
#endif //SHOW_RECENT_TAB
|
||||
getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperienceLog());
|
||||
resizeToTabs();
|
||||
|
||||
|
||||
LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
|
||||
boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperiences::clearFromRecent(const LLSD& ids)
|
||||
{
|
||||
#if SHOW_RECENT_TAB
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab");
|
||||
if(!tab)
|
||||
return;
|
||||
|
||||
tab->removeExperiences(ids);
|
||||
#endif // SHOW_RECENT_TAB
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::setupRecentTabs()
|
||||
{
|
||||
#if SHOW_RECENT_TAB
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab");
|
||||
if(!tab)
|
||||
return;
|
||||
|
||||
LLSD recent;
|
||||
|
||||
const LLExperienceCache::cache_t& experiences = LLExperienceCache::getCached();
|
||||
|
||||
LLExperienceCache::cache_t::const_iterator it = experiences.begin();
|
||||
while( it != experiences.end() )
|
||||
{
|
||||
if(!it->second.has(LLExperienceCache::MISSING))
|
||||
{
|
||||
recent.append(it->first);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
tab->setExperienceList(recent);
|
||||
#endif // SHOW_RECENT_TAB
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperiences::resizeToTabs()
|
||||
{
|
||||
const S32 TAB_WIDTH_PADDING = 16;
|
||||
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
LLRect rect = getRect();
|
||||
if(rect.getWidth() < tabs->getTotalTabWidth() + TAB_WIDTH_PADDING)
|
||||
{
|
||||
rect.mRight = rect.mLeft + tabs->getTotalTabWidth() + TAB_WIDTH_PADDING;
|
||||
}
|
||||
reshape(rect.getWidth(), rect.getHeight(), FALSE);
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::refreshContents()
|
||||
{
|
||||
setupRecentTabs();
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
|
||||
if (region)
|
||||
{
|
||||
LLExperienceListResponder::NameMap nameMap;
|
||||
std::string lookup_url=region->getCapability("GetExperiences");
|
||||
if(!lookup_url.empty())
|
||||
{
|
||||
nameMap["experiences"]="Allowed_Experiences_Tab";
|
||||
nameMap["blocked"]="Blocked_Experiences_Tab";
|
||||
LLHTTPClient::get(lookup_url, new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap));
|
||||
}
|
||||
|
||||
updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
|
||||
updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
|
||||
|
||||
lookup_url = region->getCapability("AgentExperiences");
|
||||
if(!lookup_url.empty())
|
||||
{
|
||||
nameMap["experience_ids"]="Owned_Experiences_Tab";
|
||||
LLExperienceListResponder* responder = new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap, "ExperienceAcquireFailed");
|
||||
responder->mCallback = boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2);
|
||||
LLHTTPClient::get(lookup_url, responder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::onOpen( const LLSD& key )
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if(region)
|
||||
{
|
||||
if(region->capabilitiesReceived())
|
||||
{
|
||||
refreshContents();
|
||||
return;
|
||||
}
|
||||
region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterExperiences::refreshContents, this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterExperiences::updatePermissions( const LLSD& permission )
|
||||
{
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
LLUUID experience;
|
||||
std::string permission_string;
|
||||
if(permission.has("experience"))
|
||||
{
|
||||
experience = permission["experience"].asUUID();
|
||||
permission_string = permission[experience.asString()]["permission"].asString();
|
||||
|
||||
}
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Allowed_Experiences_Tab");
|
||||
if(tab)
|
||||
{
|
||||
if(permission.has("experiences"))
|
||||
{
|
||||
tab->setExperienceList(permission["experiences"]);
|
||||
}
|
||||
else if(experience.notNull())
|
||||
{
|
||||
if(permission_string != "Allow")
|
||||
{
|
||||
tab->removeExperience(experience);
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->addExperience(experience);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tab = (LLPanelExperiences*)tabs->getPanelByName("Blocked_Experiences_Tab");
|
||||
if(tab)
|
||||
{
|
||||
if(permission.has("blocked"))
|
||||
{
|
||||
tab->setExperienceList(permission["blocked"]);
|
||||
}
|
||||
else if(experience.notNull())
|
||||
{
|
||||
if(permission_string != "Block")
|
||||
{
|
||||
tab->removeExperience(experience);
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->addExperience(experience);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::onClose( bool app_quitting )
|
||||
{
|
||||
LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
|
||||
LLFloater::onClose(app_quitting);
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content) const
|
||||
{
|
||||
panel->enableButton(content.has("purchase"));
|
||||
|
||||
LLFloaterExperiences::findInstance()->updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
|
||||
LLFloaterExperiences::findInstance()->updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::updateInfo(std::string experiences, std::string tab)
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
LLExperienceListResponder::NameMap nameMap;
|
||||
std::string lookup_url = region->getCapability(experiences);
|
||||
if(!lookup_url.empty())
|
||||
{
|
||||
nameMap["experience_ids"]=tab;
|
||||
LLHTTPClient::get(lookup_url, new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::sendPurchaseRequest() const
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
std::string url = region->getCapability("AgentExperiences");
|
||||
if(!url.empty())
|
||||
{
|
||||
LLSD content;
|
||||
|
||||
LLExperienceListResponder::NameMap nameMap;
|
||||
nameMap["experience_ids"]="Owned_Experiences_Tab";
|
||||
LLExperienceListResponder* responder = new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap, "ExperienceAcquireFailed");
|
||||
responder->mCallback = boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2);
|
||||
LLHTTPClient::post(url, content, responder);
|
||||
}
|
||||
}
|
||||
|
||||
LLFloaterExperiences* LLFloaterExperiences::findInstance()
|
||||
{
|
||||
return LLFloaterReg::findTypedInstance<LLFloaterExperiences>("experiences");
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* @file llfloaterexperiences.h
|
||||
* @brief LLFloaterExperiences class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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_LLFLOATEREXPERIENCES_H
|
||||
#define LL_LLFLOATEREXPERIENCES_H
|
||||
|
||||
#include "llfloater.h"
|
||||
|
||||
class LLPanelExperiences;
|
||||
|
||||
class LLFloaterExperiences :
|
||||
public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterExperiences(const LLSD& data);
|
||||
virtual void onClose(bool app_quitting);
|
||||
|
||||
virtual void onOpen(const LLSD& key);
|
||||
static LLFloaterExperiences* findInstance();
|
||||
protected:
|
||||
void clearFromRecent(const LLSD& ids);
|
||||
void resizeToTabs();
|
||||
/*virtual*/ BOOL postBuild();
|
||||
void refreshContents();
|
||||
void setupRecentTabs();
|
||||
LLPanelExperiences* addTab(const std::string& name, bool select);
|
||||
|
||||
bool updatePermissions(const LLSD& permission);
|
||||
void sendPurchaseRequest() const;
|
||||
void checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content)const;
|
||||
void updateInfo(std::string experiences, std::string tab);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif //LL_LLFLOATEREXPERIENCES_H
|
||||
|
|
@ -75,6 +75,9 @@
|
|||
#include "llviewercontrol.h"
|
||||
#include "roles_constants.h"
|
||||
#include "lltrans.h"
|
||||
#include "llpanelexperiencelisteditor.h"
|
||||
#include "llpanelexperiencepicker.h"
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
#include "llgroupactions.h"
|
||||
|
||||
|
|
@ -110,6 +113,28 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class LLPanelLandExperiences
|
||||
: public LLPanel
|
||||
{
|
||||
public:
|
||||
LLPanelLandExperiences(LLSafeHandle<LLParcelSelection>& parcelp);
|
||||
virtual BOOL postBuild();
|
||||
void refresh();
|
||||
|
||||
void experienceAdded(const LLUUID& id, U32 xp_type, U32 access_type);
|
||||
void experienceRemoved(const LLUUID& id, U32 access_type);
|
||||
protected:
|
||||
LLPanelExperienceListEditor* setupList( const char* control_name, U32 xp_type, U32 access_type );
|
||||
void refreshPanel(LLPanelExperienceListEditor* panel, U32 xp_type);
|
||||
|
||||
LLSafeHandle<LLParcelSelection>& mParcel;
|
||||
|
||||
|
||||
LLPanelExperienceListEditor* mAllowed;
|
||||
LLPanelExperienceListEditor* mBlocked;
|
||||
};
|
||||
|
||||
// inserts maturity info(icon and text) into target textbox
|
||||
// names_floater - pointer to floater which contains strings with maturity icons filenames
|
||||
// str_to_parse is string in format "txt1[MATURITY]txt2" where maturity icon and text will be inserted instead of [MATURITY]
|
||||
|
|
@ -248,6 +273,7 @@ LLFloaterLand::LLFloaterLand(const LLSD& seed)
|
|||
mFactoryMap["land_audio_panel"] = LLCallbackMap(createPanelLandAudio, this);
|
||||
mFactoryMap["land_media_panel"] = LLCallbackMap(createPanelLandMedia, this);
|
||||
mFactoryMap["land_access_panel"] = LLCallbackMap(createPanelLandAccess, this);
|
||||
mFactoryMap["land_experiences_panel"] = LLCallbackMap(createPanelLandExperiences, this);
|
||||
|
||||
sObserver = new LLParcelSelectionObserver();
|
||||
LLViewerParcelMgr::getInstance()->addObserver( sObserver );
|
||||
|
|
@ -288,6 +314,7 @@ void LLFloaterLand::refresh()
|
|||
mPanelMedia->refresh();
|
||||
mPanelAccess->refresh();
|
||||
mPanelCovenant->refresh();
|
||||
mPanelExperiences->refresh();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -348,6 +375,15 @@ void* LLFloaterLand::createPanelLandAccess(void* data)
|
|||
return self->mPanelAccess;
|
||||
}
|
||||
|
||||
// static
|
||||
void* LLFloaterLand::createPanelLandExperiences(void* data)
|
||||
{
|
||||
LLFloaterLand* self = (LLFloaterLand*)data;
|
||||
self->mPanelExperiences = new LLPanelLandExperiences(self->mParcel);
|
||||
return self->mPanelExperiences;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPanelLandGeneral
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -2404,7 +2440,7 @@ void LLPanelLandAccess::refresh()
|
|||
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
|
||||
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
|
||||
|
||||
for (access_map_const_iterator cit = parcel->mAccessList.begin();
|
||||
for (LLAccessEntry::map::const_iterator cit = parcel->mAccessList.begin();
|
||||
cit != parcel->mAccessList.end(); ++cit)
|
||||
{
|
||||
const LLAccessEntry& entry = (*cit).second;
|
||||
|
|
@ -2450,7 +2486,7 @@ void LLPanelLandAccess::refresh()
|
|||
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
|
||||
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
|
||||
|
||||
for (access_map_const_iterator cit = parcel->mBanList.begin();
|
||||
for (LLAccessEntry::map::const_iterator cit = parcel->mBanList.begin();
|
||||
cit != parcel->mBanList.end(); ++cit)
|
||||
{
|
||||
const LLAccessEntry& entry = (*cit).second;
|
||||
|
|
@ -3039,3 +3075,103 @@ void insert_maturity_into_textbox(LLTextBox* target_textbox, LLFloater* names_fl
|
|||
target_textbox->appendText(LLViewerParcelMgr::getInstance()->getSelectionRegion()->getSimAccessString(), false);
|
||||
target_textbox->appendText(text_after_rating, false);
|
||||
}
|
||||
|
||||
LLPanelLandExperiences::LLPanelLandExperiences( LLSafeHandle<LLParcelSelection>& parcelp )
|
||||
: mParcel(parcelp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOL LLPanelLandExperiences::postBuild()
|
||||
{
|
||||
mAllowed = setupList("panel_allowed", EXPERIENCE_KEY_TYPE_ALLOWED, AL_ALLOW_EXPERIENCE);
|
||||
mBlocked = setupList("panel_blocked", EXPERIENCE_KEY_TYPE_BLOCKED, AL_BLOCK_EXPERIENCE);
|
||||
|
||||
// only non-grid-wide experiences
|
||||
mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID));
|
||||
|
||||
// no privileged ones
|
||||
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperties, _1, LLExperienceCache::PROPERTY_PRIVILEGED|LLExperienceCache::PROPERTY_GRID));
|
||||
|
||||
getChild<LLLayoutPanel>("trusted_layout_panel")->setVisible(FALSE);
|
||||
getChild<LLTextBox>("experiences_help_text")->setVisible(FALSE);
|
||||
getChild<LLTextBox>("allowed_text_help")->setText(getString("allowed_parcel_text"));
|
||||
getChild<LLTextBox>("blocked_text_help")->setText(getString("blocked_parcel_text"));
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
LLPanelExperienceListEditor* LLPanelLandExperiences::setupList( const char* control_name, U32 xp_type, U32 access_type )
|
||||
{
|
||||
LLPanelExperienceListEditor* child = findChild<LLPanelExperienceListEditor>(control_name);
|
||||
if(child)
|
||||
{
|
||||
child->getChild<LLTextBox>("text_name")->setText(child->getString(control_name));
|
||||
child->setMaxExperienceIDs(PARCEL_MAX_EXPERIENCE_LIST);
|
||||
child->setAddedCallback(boost::bind(&LLPanelLandExperiences::experienceAdded, this, _1, xp_type, access_type));
|
||||
child->setRemovedCallback(boost::bind(&LLPanelLandExperiences::experienceRemoved, this, _1, access_type));
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
void LLPanelLandExperiences::experienceAdded( const LLUUID& id, U32 xp_type, U32 access_type )
|
||||
{
|
||||
LLParcel* parcel = mParcel->getParcel();
|
||||
if (parcel)
|
||||
{
|
||||
parcel->setExperienceKeyType(id, xp_type);
|
||||
LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(access_type);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelLandExperiences::experienceRemoved( const LLUUID& id, U32 access_type )
|
||||
{
|
||||
LLParcel* parcel = mParcel->getParcel();
|
||||
if (parcel)
|
||||
{
|
||||
parcel->setExperienceKeyType(id, EXPERIENCE_KEY_TYPE_NONE);
|
||||
LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(access_type);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelLandExperiences::refreshPanel(LLPanelExperienceListEditor* panel, U32 xp_type)
|
||||
{
|
||||
LLParcel *parcel = mParcel->getParcel();
|
||||
|
||||
// Display options
|
||||
if (panel == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (parcel == NULL)
|
||||
{
|
||||
// disable the panel
|
||||
panel->setEnabled(FALSE);
|
||||
panel->setExperienceIds(LLSD::emptyArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
// enable the panel
|
||||
panel->setEnabled(TRUE);
|
||||
LLAccessEntry::map entries = parcel->getExperienceKeysByType(xp_type);
|
||||
LLAccessEntry::map::iterator it = entries.begin();
|
||||
LLSD ids = LLSD::emptyArray();
|
||||
for (/**/; it != entries.end(); ++it)
|
||||
{
|
||||
ids.append(it->second.mID);
|
||||
}
|
||||
panel->setExperienceIds(ids);
|
||||
panel->setReadonly(!LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_OPTIONS));
|
||||
panel->refreshExperienceCounter();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelLandExperiences::refresh()
|
||||
{
|
||||
refreshPanel(mAllowed, EXPERIENCE_KEY_TYPE_ALLOWED);
|
||||
refreshPanel(mBlocked, EXPERIENCE_KEY_TYPE_BLOCKED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ class LLPanelLandBan;
|
|||
class LLPanelLandRenters;
|
||||
class LLPanelLandCovenant;
|
||||
class LLParcel;
|
||||
class LLPanelLandExperiences;
|
||||
|
||||
class LLFloaterLand
|
||||
: public LLFloater
|
||||
|
|
@ -101,6 +102,7 @@ protected:
|
|||
static void* createPanelLandAudio(void* data);
|
||||
static void* createPanelLandMedia(void* data);
|
||||
static void* createPanelLandAccess(void* data);
|
||||
static void* createPanelLandExperiences(void* data);
|
||||
static void* createPanelLandBan(void* data);
|
||||
|
||||
|
||||
|
|
@ -116,6 +118,7 @@ protected:
|
|||
LLPanelLandMedia* mPanelMedia;
|
||||
LLPanelLandAccess* mPanelAccess;
|
||||
LLPanelLandCovenant* mPanelCovenant;
|
||||
LLPanelLandExperiences* mPanelExperiences;
|
||||
|
||||
LLSafeHandle<LLParcelSelection> mParcel;
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,11 @@
|
|||
#include "llagentui.h"
|
||||
#include "llmeshrepository.h"
|
||||
#include "llfloaterregionrestarting.h"
|
||||
#include "llpanelexperiencelisteditor.h"
|
||||
#include <boost/function.hpp>
|
||||
#include "llpanelexperiencepicker.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llpanelexperiences.h"
|
||||
#include "llcorehttputil.h"
|
||||
|
||||
const S32 TERRAIN_TEXTURE_COUNT = 4;
|
||||
|
|
@ -127,6 +132,18 @@ public:
|
|||
const sparam_t& strings);
|
||||
};
|
||||
|
||||
class LLDispatchSetEstateExperience : public LLDispatchHandler
|
||||
{
|
||||
public:
|
||||
virtual bool operator()(
|
||||
const LLDispatcher* dispatcher,
|
||||
const std::string& key,
|
||||
const LLUUID& invoice,
|
||||
const sparam_t& strings);
|
||||
|
||||
LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count );
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
void unpack_request_params(
|
||||
|
|
@ -216,6 +233,14 @@ BOOL LLFloaterRegionInfo::postBuild()
|
|||
panel->buildFromFile("panel_region_debug.xml");
|
||||
mTab->addTabPanel(panel);
|
||||
|
||||
if(!gAgent.getRegion()->getCapability("RegionExperiences").empty())
|
||||
{
|
||||
panel = new LLPanelRegionExperiences;
|
||||
mInfoPanels.push_back(panel);
|
||||
panel->buildFromFile("panel_region_experiences.xml");
|
||||
mTab->addTabPanel(panel);
|
||||
}
|
||||
|
||||
gMessageSystem->setHandlerFunc(
|
||||
"EstateOwnerMessage",
|
||||
&processEstateOwnerRequest);
|
||||
|
|
@ -446,6 +471,16 @@ LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain()
|
|||
return panel;
|
||||
}
|
||||
|
||||
LLPanelRegionExperiences* LLFloaterRegionInfo::getPanelExperiences()
|
||||
{
|
||||
LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
|
||||
if (!floater) return NULL;
|
||||
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
|
||||
return (LLPanelRegionExperiences*)tab->getChild<LLPanel>("Experiences");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLFloaterRegionInfo::onTabSelected(const LLSD& param)
|
||||
{
|
||||
LLPanel* active_panel = getChild<LLPanel>(param.asString());
|
||||
|
|
@ -1370,6 +1405,11 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch)
|
|||
static LLDispatchSetEstateAccess set_access;
|
||||
dispatch.addHandler(name, &set_access);
|
||||
|
||||
|
||||
name.assign("setexperience");
|
||||
static LLDispatchSetEstateExperience set_experience;
|
||||
dispatch.addHandler(name, &set_experience);
|
||||
|
||||
estate_dispatch_initialized = true;
|
||||
}
|
||||
|
||||
|
|
@ -2849,6 +2889,56 @@ bool LLDispatchSetEstateAccess::operator()(
|
|||
return true;
|
||||
}
|
||||
|
||||
LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count )
|
||||
{
|
||||
LLSD idList = LLSD::emptyArray();
|
||||
LLUUID id;
|
||||
while(count--> 0)
|
||||
{
|
||||
memcpy(id.mData, (*(it++)).data(), UUID_BYTES);
|
||||
idList.append(id);
|
||||
}
|
||||
return idList;
|
||||
}
|
||||
|
||||
// key = "setexperience"
|
||||
// strings[0] = str(estate_id)
|
||||
// strings[1] = str(send_to_agent_only)
|
||||
// strings[2] = str(num blocked)
|
||||
// strings[3] = str(num trusted)
|
||||
// strings[4] = str(num allowed)
|
||||
// strings[8] = bin(uuid) ...
|
||||
// ...
|
||||
bool LLDispatchSetEstateExperience::operator()(
|
||||
const LLDispatcher* dispatcher,
|
||||
const std::string& key,
|
||||
const LLUUID& invoice,
|
||||
const sparam_t& strings)
|
||||
{
|
||||
LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences();
|
||||
if (!panel) return true;
|
||||
|
||||
sparam_t::const_iterator it = strings.begin();
|
||||
++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10);
|
||||
++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10);
|
||||
|
||||
LLUUID id;
|
||||
S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10);
|
||||
S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10);
|
||||
S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10);
|
||||
|
||||
LLSD ids = LLSD::emptyMap()
|
||||
.with("blocked", getIDs(it, strings.end(), num_blocked))
|
||||
.with("trusted", getIDs(it + (num_blocked), strings.end(), num_trusted))
|
||||
.with("allowed", getIDs(it + (num_blocked+num_trusted), strings.end(), num_allowed));
|
||||
|
||||
panel->processResponse(ids);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLPanelEnvironmentInfo::LLPanelEnvironmentInfo()
|
||||
: mEnableEditing(false),
|
||||
mRegionSettingsRadioGroup(NULL),
|
||||
|
|
@ -3440,3 +3530,284 @@ void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok)
|
|||
LLEnvManagerNew::instance().requestRegionSettings();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLPanelRegionExperiences::postBuild()
|
||||
{
|
||||
mAllowed = setupList("panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE);
|
||||
mTrusted = setupList("panel_trusted", ESTATE_EXPERIENCE_TRUSTED_ADD, ESTATE_EXPERIENCE_TRUSTED_REMOVE);
|
||||
mBlocked = setupList("panel_blocked", ESTATE_EXPERIENCE_BLOCKED_ADD, ESTATE_EXPERIENCE_BLOCKED_REMOVE);
|
||||
|
||||
getChild<LLLayoutPanel>("trusted_layout_panel")->setVisible(TRUE);
|
||||
getChild<LLTextBox>("experiences_help_text")->setText(getString("estate_caption"));
|
||||
getChild<LLTextBox>("trusted_text_help")->setText(getString("trusted_estate_text"));
|
||||
getChild<LLTextBox>("allowed_text_help")->setText(getString("allowed_estate_text"));
|
||||
getChild<LLTextBox>("blocked_text_help")->setText(getString("blocked_estate_text"));
|
||||
|
||||
return LLPanelRegionInfo::postBuild();
|
||||
}
|
||||
|
||||
LLPanelExperienceListEditor* LLPanelRegionExperiences::setupList( const char* control_name, U32 add_id, U32 remove_id )
|
||||
{
|
||||
LLPanelExperienceListEditor* child = findChild<LLPanelExperienceListEditor>(control_name);
|
||||
if(child)
|
||||
{
|
||||
child->getChild<LLTextBox>("text_name")->setText(child->getString(control_name));
|
||||
child->setMaxExperienceIDs(ESTATE_MAX_EXPERIENCE_IDS);
|
||||
child->setAddedCallback( boost::bind(&LLPanelRegionExperiences::itemChanged, this, add_id, _1));
|
||||
child->setRemovedCallback(boost::bind(&LLPanelRegionExperiences::itemChanged, this, remove_id, _1));
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
void LLPanelRegionExperiences::processResponse( const LLSD& content )
|
||||
{
|
||||
if(content.has("default"))
|
||||
{
|
||||
mDefaultExperience = content["default"].asUUID();
|
||||
}
|
||||
|
||||
mAllowed->setExperienceIds(content["allowed"]);
|
||||
mBlocked->setExperienceIds(content["blocked"]);
|
||||
|
||||
LLSD trusted = content["trusted"];
|
||||
if(mDefaultExperience.notNull())
|
||||
{
|
||||
mTrusted->setStickyFunction(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience));
|
||||
trusted.append(mDefaultExperience);
|
||||
}
|
||||
|
||||
mTrusted->setExperienceIds(trusted);
|
||||
|
||||
mAllowed->refreshExperienceCounter();
|
||||
mBlocked->refreshExperienceCounter();
|
||||
mTrusted->refreshExperienceCounter();
|
||||
|
||||
}
|
||||
|
||||
|
||||
class LLRegionExperienceResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void (const LLSD&)> callback_t;
|
||||
|
||||
callback_t mCallback;
|
||||
|
||||
LLRegionExperienceResponder(callback_t callback) : mCallback(callback) { }
|
||||
|
||||
protected:
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
mCallback(getContent());
|
||||
}
|
||||
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Used for both access add and remove operations, depending on the flag
|
||||
// passed in (ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE, etc.)
|
||||
// static
|
||||
bool LLPanelRegionExperiences::experienceCoreConfirm(const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger();
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
|
||||
LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray();
|
||||
|
||||
for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray();
|
||||
iter != end_it;
|
||||
iter++)
|
||||
{
|
||||
U32 flags = originalFlags;
|
||||
if (iter + 1 != end_it)
|
||||
flags |= ESTATE_ACCESS_NO_REPLY;
|
||||
|
||||
const LLUUID id = iter->asUUID();
|
||||
switch(option)
|
||||
{
|
||||
case 0:
|
||||
// This estate
|
||||
sendEstateExperienceDelta(flags, id);
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
// All estates, either than I own or manage for this owner.
|
||||
// This will be verified on simulator. JC
|
||||
if (!region) break;
|
||||
if (region->getOwner() == gAgent.getID()
|
||||
|| gAgent.isGodlike())
|
||||
{
|
||||
flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES;
|
||||
sendEstateExperienceDelta(flags, id);
|
||||
}
|
||||
else if (region->isEstateManager())
|
||||
{
|
||||
flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES;
|
||||
sendEstateExperienceDelta(flags, id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Send the actual "estateexperiencedelta" message
|
||||
void LLPanelRegionExperiences::sendEstateExperienceDelta(U32 flags, const LLUUID& experience_id)
|
||||
{
|
||||
strings_t str(3, std::string());
|
||||
gAgent.getID().toString(str[0]);
|
||||
str[1] = llformat("%u", flags);
|
||||
experience_id.toString(str[2]);
|
||||
|
||||
LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences();
|
||||
if (panel)
|
||||
{
|
||||
panel->sendEstateOwnerMessage(gMessageSystem, "estateexperiencedelta", LLFloaterRegionInfo::getLastInvoice(), str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLPanelRegionExperiences::infoCallback(LLHandle<LLPanelRegionExperiences> handle, const LLSD& content)
|
||||
{
|
||||
if(handle.isDead())
|
||||
return;
|
||||
|
||||
LLPanelRegionExperiences* floater = handle.get();
|
||||
if (floater)
|
||||
{
|
||||
floater->processResponse(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
|
||||
{
|
||||
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
|
||||
|
||||
mAllowed->loading();
|
||||
mAllowed->setReadonly(!allow_modify);
|
||||
// remove grid-wide experiences
|
||||
mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID));
|
||||
// remove default experience
|
||||
mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience));
|
||||
|
||||
mBlocked->loading();
|
||||
mBlocked->setReadonly(!allow_modify);
|
||||
// only grid-wide experiences
|
||||
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID));
|
||||
// but not privileged ones
|
||||
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED));
|
||||
// remove default experience
|
||||
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience));
|
||||
|
||||
mTrusted->loading();
|
||||
mTrusted->setReadonly(!allow_modify);
|
||||
|
||||
std::string url = region->getCapability("RegionExperiences");
|
||||
if (!url.empty())
|
||||
{
|
||||
LLHTTPClient::get(url, new LLRegionExperienceResponder(boost::bind(&LLPanelRegionExperiences::infoCallback,
|
||||
getDerivedHandle<LLPanelRegionExperiences>(), _1)));
|
||||
}
|
||||
return LLPanelRegionInfo::refreshFromRegion(region);
|
||||
}
|
||||
|
||||
LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel)
|
||||
{
|
||||
LLSD ids;
|
||||
const uuid_list_t& id_list = panel->getExperienceIds();
|
||||
for(uuid_list_t::const_iterator it = id_list.begin(); it != id_list.end(); ++it)
|
||||
{
|
||||
ids.append(*it);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLPanelRegionExperiences::sendUpdate()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
std::string url = region->getCapability("RegionExperiences");
|
||||
if (!url.empty())
|
||||
{
|
||||
LLSD content;
|
||||
|
||||
content["allowed"]=addIds(mAllowed);
|
||||
content["blocked"]=addIds(mBlocked);
|
||||
content["trusted"]=addIds(mTrusted);
|
||||
|
||||
LLHTTPClient::post(url, content, new LLRegionExperienceResponder(boost::bind(&LLPanelRegionExperiences::infoCallback,
|
||||
getDerivedHandle<LLPanelRegionExperiences>(), _1)));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLPanelRegionExperiences::itemChanged( U32 event_type, const LLUUID& id )
|
||||
{
|
||||
std::string dialog_name;
|
||||
switch (event_type)
|
||||
{
|
||||
case ESTATE_EXPERIENCE_ALLOWED_ADD:
|
||||
dialog_name = "EstateAllowedExperienceAdd";
|
||||
break;
|
||||
|
||||
case ESTATE_EXPERIENCE_ALLOWED_REMOVE:
|
||||
dialog_name = "EstateAllowedExperienceRemove";
|
||||
break;
|
||||
|
||||
case ESTATE_EXPERIENCE_TRUSTED_ADD:
|
||||
dialog_name = "EstateTrustedExperienceAdd";
|
||||
break;
|
||||
|
||||
case ESTATE_EXPERIENCE_TRUSTED_REMOVE:
|
||||
dialog_name = "EstateTrustedExperienceRemove";
|
||||
break;
|
||||
|
||||
case ESTATE_EXPERIENCE_BLOCKED_ADD:
|
||||
dialog_name = "EstateBlockedExperienceAdd";
|
||||
break;
|
||||
|
||||
case ESTATE_EXPERIENCE_BLOCKED_REMOVE:
|
||||
dialog_name = "EstateBlockedExperienceRemove";
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD payload;
|
||||
payload["operation"] = (S32)event_type;
|
||||
payload["dialog_name"] = dialog_name;
|
||||
payload["allowed_ids"].append(id);
|
||||
|
||||
LLSD args;
|
||||
args["ALL_ESTATES"] = all_estates_text();
|
||||
|
||||
LLNotification::Params params(dialog_name);
|
||||
params.payload(payload)
|
||||
.substitutions(args)
|
||||
.functor.function(LLPanelRegionExperiences::experienceCoreConfirm);
|
||||
if (LLPanelEstateInfo::isLindenEstate())
|
||||
{
|
||||
LLNotifications::instance().forceResponse(params, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotifications::instance().add(params);
|
||||
}
|
||||
|
||||
onChangeAnything();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ class LLPanelRegionDebugInfo;
|
|||
class LLPanelRegionTerrainInfo;
|
||||
class LLPanelEstateInfo;
|
||||
class LLPanelEstateCovenant;
|
||||
class LLPanelExperienceListEditor;
|
||||
class LLPanelExperiences;
|
||||
class LLPanelRegionExperiences;
|
||||
|
||||
class LLEventTimer;
|
||||
class LLEnvironmentSettings;
|
||||
|
|
@ -91,6 +94,7 @@ public:
|
|||
static LLPanelEstateInfo* getPanelEstate();
|
||||
static LLPanelEstateCovenant* getPanelCovenant();
|
||||
static LLPanelRegionTerrainInfo* getPanelRegionTerrain();
|
||||
static LLPanelRegionExperiences* getPanelExperiences();
|
||||
|
||||
// from LLPanel
|
||||
virtual void refresh();
|
||||
|
|
@ -456,4 +460,34 @@ private:
|
|||
LLComboBox* mDayCyclePresetCombo;
|
||||
};
|
||||
|
||||
class LLPanelRegionExperiences : public LLPanelRegionInfo
|
||||
{
|
||||
LOG_CLASS(LLPanelEnvironmentInfo);
|
||||
|
||||
public:
|
||||
LLPanelRegionExperiences(){}
|
||||
/*virtual*/ BOOL postBuild();
|
||||
virtual BOOL sendUpdate();
|
||||
|
||||
static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response);
|
||||
static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id);
|
||||
|
||||
static void infoCallback(LLHandle<LLPanelRegionExperiences> handle, const LLSD& content);
|
||||
bool refreshFromRegion(LLViewerRegion* region);
|
||||
void sendPurchaseRequest()const;
|
||||
void processResponse( const LLSD& content );
|
||||
private:
|
||||
void refreshRegionExperiences();
|
||||
|
||||
LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id);
|
||||
static LLSD addIds( LLPanelExperienceListEditor* panel );
|
||||
|
||||
void itemChanged(U32 event_type, const LLUUID& id);
|
||||
|
||||
LLPanelExperienceListEditor* mTrusted;
|
||||
LLPanelExperienceListEditor* mAllowed;
|
||||
LLPanelExperienceListEditor* mBlocked;
|
||||
LLUUID mDefaultExperience;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@
|
|||
#include "llagentui.h"
|
||||
|
||||
#include "lltrans.h"
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Globals
|
||||
|
|
@ -225,6 +226,30 @@ void LLFloaterReporter::enableControls(BOOL enable)
|
|||
getChildView("cancel_btn")->setEnabled(enable);
|
||||
}
|
||||
|
||||
void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id)
|
||||
{
|
||||
mExperienceID = experience_id;
|
||||
|
||||
if (LLUUID::null != mExperienceID)
|
||||
{
|
||||
const LLSD& experience = LLExperienceCache::get(mExperienceID);
|
||||
std::stringstream desc;
|
||||
|
||||
if(experience.isDefined())
|
||||
{
|
||||
setFromAvatarID(experience[LLExperienceCache::AGENT_ID]);
|
||||
desc << "Experience id: " << mExperienceID;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc << "Unable to retrieve details for id: "<< mExperienceID;
|
||||
}
|
||||
|
||||
LLUICtrl* details = getChild<LLUICtrl>("details_edit");
|
||||
details->setValue(desc.str());
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
|
||||
{
|
||||
// TODO --
|
||||
|
|
@ -470,7 +495,7 @@ void LLFloaterReporter::showFromMenu(EReportType report_type)
|
|||
}
|
||||
|
||||
// static
|
||||
void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name)
|
||||
void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name, const LLUUID& experience_id)
|
||||
{
|
||||
LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
|
||||
|
||||
|
|
@ -483,6 +508,23 @@ void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_
|
|||
{
|
||||
f->setFromAvatarID(object_id);
|
||||
}
|
||||
if(experience_id.notNull())
|
||||
{
|
||||
f->getExperienceInfo(experience_id);
|
||||
}
|
||||
|
||||
// Need to deselect on close
|
||||
f->mDeselectOnClose = TRUE;
|
||||
|
||||
f->openFloater();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLFloaterReporter::showFromExperience( const LLUUID& experience_id )
|
||||
{
|
||||
LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
|
||||
f->getExperienceInfo(experience_id);
|
||||
|
||||
// Need to deselect on close
|
||||
f->mDeselectOnClose = TRUE;
|
||||
|
|
@ -492,9 +534,9 @@ void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_
|
|||
|
||||
|
||||
// static
|
||||
void LLFloaterReporter::showFromObject(const LLUUID& object_id)
|
||||
void LLFloaterReporter::showFromObject(const LLUUID& object_id, const LLUUID& experience_id)
|
||||
{
|
||||
show(object_id);
|
||||
show(object_id, LLStringUtil::null, experience_id);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -854,6 +896,7 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos)
|
|||
getChild<LLUICtrl>("pos_field")->setValue(pos_string);
|
||||
}
|
||||
|
||||
|
||||
// void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
|
||||
// {
|
||||
// LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
|
||||
|
|
|
|||
|
|
@ -88,8 +88,9 @@ public:
|
|||
// Enables all buttons
|
||||
static void showFromMenu(EReportType report_type);
|
||||
|
||||
static void showFromObject(const LLUUID& object_id);
|
||||
static void showFromObject(const LLUUID& object_id, const LLUUID& experience_id = LLUUID::null);
|
||||
static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name);
|
||||
static void showFromExperience(const LLUUID& experience_id);
|
||||
|
||||
static void onClickSend (void *userdata);
|
||||
static void onClickCancel (void *userdata);
|
||||
|
|
@ -106,7 +107,7 @@ public:
|
|||
void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id);
|
||||
|
||||
private:
|
||||
static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null);
|
||||
static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null, const LLUUID& experience_id = LLUUID::null);
|
||||
|
||||
void takeScreenshot();
|
||||
void sendReportViaCaps(std::string url);
|
||||
|
|
@ -118,6 +119,7 @@ private:
|
|||
void sendReportViaCaps(std::string url, std::string sshot_url, const LLSD & report);
|
||||
void setPosBox(const LLVector3d &pos);
|
||||
void enableControls(BOOL own_avatar);
|
||||
void getExperienceInfo(const LLUUID& object_id);
|
||||
void getObjectInfo(const LLUUID& object_id);
|
||||
void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
|
||||
void setFromAvatarID(const LLUUID& avatar_id);
|
||||
|
|
@ -128,6 +130,7 @@ private:
|
|||
LLUUID mObjectID;
|
||||
LLUUID mScreenID;
|
||||
LLUUID mAbuserID;
|
||||
LLUUID mExperienceID;
|
||||
// Store the real name, not the link, for upstream reporting
|
||||
std::string mOwnerName;
|
||||
BOOL mDeselectOnClose;
|
||||
|
|
|
|||
|
|
@ -169,7 +169,9 @@ public:
|
|||
virtual ~LLScriptHandler();
|
||||
|
||||
virtual void onDelete(LLNotificationPtr p);
|
||||
virtual void onChange(LLNotificationPtr p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
virtual void addToastWithNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void onDeleteToast(LLToast* toast);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,30 @@ void LLScriptHandler::initChannel()
|
|||
mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void LLScriptHandler::addToastWithNotification(const LLNotificationPtr& notification)
|
||||
{
|
||||
LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification);
|
||||
|
||||
LLToast::Params p;
|
||||
p.notif_id = notification->getID();
|
||||
p.notification = notification;
|
||||
p.panel = notify_box;
|
||||
p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1);
|
||||
if(gAgent.isDoNotDisturb())
|
||||
{
|
||||
p.force_show = notification->getName() == "SystemMessage"
|
||||
|| notification->getName() == "GodMessage"
|
||||
|| notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
|
||||
}
|
||||
|
||||
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
|
||||
if(channel)
|
||||
{
|
||||
channel->addToast(p);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)
|
||||
{
|
||||
|
|
@ -92,42 +116,33 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)
|
|||
}
|
||||
else if (notification->canShowToast())
|
||||
{
|
||||
LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification);
|
||||
|
||||
LLToast::Params p;
|
||||
p.notif_id = notification->getID();
|
||||
p.notification = notification;
|
||||
p.panel = notify_box;
|
||||
p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1);
|
||||
if(gAgent.isDoNotDisturb())
|
||||
{
|
||||
p.force_show = notification->getName() == "SystemMessage"
|
||||
|| notification->getName() == "GodMessage"
|
||||
|| notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
|
||||
}
|
||||
|
||||
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
|
||||
if(channel)
|
||||
{
|
||||
channel->addToast(p);
|
||||
}
|
||||
addToastWithNotification(notification);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLScriptHandler::onChange( LLNotificationPtr notification )
|
||||
{
|
||||
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());
|
||||
if (channel)
|
||||
{
|
||||
channel->removeToastByNotificationID(notification->getID());
|
||||
addToastWithNotification(notification);
|
||||
}
|
||||
}
|
||||
|
||||
void LLScriptHandler::onDelete( LLNotificationPtr notification )
|
||||
{
|
||||
{
|
||||
if(notification->hasFormElements() && !notification->canShowToast())
|
||||
{
|
||||
LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());
|
||||
}
|
||||
else
|
||||
{
|
||||
mChannel.get()->removeToastByNotificationID(notification->getID());
|
||||
}
|
||||
{
|
||||
LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());
|
||||
}
|
||||
else
|
||||
{
|
||||
mChannel.get()->removeToastByNotificationID(notification->getID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,262 @@
|
|||
/**
|
||||
* @file llpanelexperiencelisteditor.cpp
|
||||
* @brief Editor for building a list of experiences
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&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 "llpanelexperiencelisteditor.h"
|
||||
|
||||
#include "llbutton.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llfloaterexperiencepicker.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llhandle.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llagent.h"
|
||||
#include "lltextbox.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
|
||||
static LLPanelInjector<LLPanelExperienceListEditor> t_panel_experience_list_editor("panel_experience_list_editor");
|
||||
|
||||
|
||||
LLPanelExperienceListEditor::LLPanelExperienceListEditor()
|
||||
:mItems(NULL)
|
||||
,mProfile(NULL)
|
||||
,mRemove(NULL)
|
||||
,mReadonly(false)
|
||||
,mMaxExperienceIDs(0)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLPanelExperienceListEditor::postBuild()
|
||||
{
|
||||
mItems = getChild<LLScrollListCtrl>("experience_list");
|
||||
mAdd = getChild<LLButton>("btn_add");
|
||||
mRemove = getChild<LLButton>("btn_remove");
|
||||
mProfile = getChild<LLButton>("btn_profile");
|
||||
|
||||
childSetAction("btn_add", boost::bind(&LLPanelExperienceListEditor::onAdd, this));
|
||||
childSetAction("btn_remove", boost::bind(&LLPanelExperienceListEditor::onRemove, this));
|
||||
childSetAction("btn_profile", boost::bind(&LLPanelExperienceListEditor::onProfile, this));
|
||||
|
||||
mItems->setCommitCallback(boost::bind(&LLPanelExperienceListEditor::checkButtonsEnabled, this));
|
||||
|
||||
checkButtonsEnabled();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const uuid_list_t& LLPanelExperienceListEditor::getExperienceIds() const
|
||||
{
|
||||
return mExperienceIds;
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::addExperienceIds( const uuid_vec_t& experience_ids )
|
||||
{
|
||||
// the commented out code in this function is handled by the callback and no longer necessary!
|
||||
|
||||
//mExperienceIds.insert(experience_ids.begin(), experience_ids.end());
|
||||
//onItems();
|
||||
if(!mAddedCallback.empty())
|
||||
{
|
||||
for(uuid_vec_t::const_iterator it = experience_ids.begin(); it != experience_ids.end(); ++it)
|
||||
{
|
||||
mAddedCallback(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLPanelExperienceListEditor::setExperienceIds( const LLSD& experience_ids )
|
||||
{
|
||||
mExperienceIds.clear();
|
||||
mExperienceIds.insert(experience_ids.beginArray(), experience_ids.endArray());
|
||||
onItems();
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::addExperience( const LLUUID& id )
|
||||
{
|
||||
mExperienceIds.insert(id);
|
||||
onItems();
|
||||
}
|
||||
void LLPanelExperienceListEditor::onAdd()
|
||||
{
|
||||
if(!mPicker.isDead())
|
||||
{
|
||||
mPicker.markDead();
|
||||
}
|
||||
|
||||
mKey.generateNewID();
|
||||
|
||||
LLFloaterExperiencePicker* picker=LLFloaterExperiencePicker::show(boost::bind(&LLPanelExperienceListEditor::addExperienceIds, this, _1), mKey, FALSE, TRUE, mFilters, mAdd);
|
||||
mPicker = picker->getDerivedHandle<LLFloaterExperiencePicker>();
|
||||
}
|
||||
|
||||
|
||||
void LLPanelExperienceListEditor::onRemove()
|
||||
{
|
||||
// the commented out code in this function is handled by the callback and no longer necessary!
|
||||
|
||||
std::vector<LLScrollListItem*> items= mItems->getAllSelected();
|
||||
std::vector<LLScrollListItem*>::iterator it = items.begin();
|
||||
for(/**/; it != items.end(); ++it)
|
||||
{
|
||||
if((*it) != NULL)
|
||||
{
|
||||
//mExperienceIds.erase((*it)->getValue());
|
||||
mRemovedCallback((*it)->getValue());
|
||||
}
|
||||
}
|
||||
mItems->selectFirstItem();
|
||||
checkButtonsEnabled();
|
||||
//onItems();
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::onProfile()
|
||||
{
|
||||
LLScrollListItem* item = mItems->getFirstSelected();
|
||||
if(item)
|
||||
{
|
||||
LLFloaterReg::showInstance("experience_profile", item->getUUID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::checkButtonsEnabled()
|
||||
{
|
||||
mAdd->setEnabled(!mReadonly);
|
||||
int selected = mItems->getNumSelected();
|
||||
|
||||
bool remove_enabled = !mReadonly && selected>0;
|
||||
if(remove_enabled && mSticky)
|
||||
{
|
||||
std::vector<LLScrollListItem*> items= mItems->getAllSelected();
|
||||
std::vector<LLScrollListItem*>::iterator it = items.begin();
|
||||
for(/**/; it != items.end() && remove_enabled; ++it)
|
||||
{
|
||||
if((*it) != NULL)
|
||||
{
|
||||
remove_enabled = !mSticky((*it)->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
mRemove->setEnabled(remove_enabled);
|
||||
mProfile->setEnabled(selected==1);
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::onItems()
|
||||
{
|
||||
mItems->deleteAllItems();
|
||||
|
||||
LLSD item;
|
||||
uuid_list_t::iterator it = mExperienceIds.begin();
|
||||
for(/**/; it != mExperienceIds.end(); ++it)
|
||||
{
|
||||
const LLUUID& experience = *it;
|
||||
item["id"]=experience;
|
||||
LLSD& columns = item["columns"];
|
||||
columns[0]["column"] = "experience_name";
|
||||
columns[0]["value"] = getString("loading");
|
||||
mItems->addElement(item);
|
||||
|
||||
LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,
|
||||
getDerivedHandle<LLPanelExperienceListEditor>(), _1));
|
||||
}
|
||||
|
||||
|
||||
if(mItems->getItemCount() == 0)
|
||||
{
|
||||
mItems->setCommentText(getString("no_results"));
|
||||
}
|
||||
|
||||
|
||||
checkButtonsEnabled();
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::experienceDetailsCallback( LLHandle<LLPanelExperienceListEditor> panel, const LLSD& experience )
|
||||
{
|
||||
if(!panel.isDead())
|
||||
{
|
||||
panel.get()->onExperienceDetails(experience);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::onExperienceDetails( const LLSD& experience )
|
||||
{
|
||||
LLScrollListItem* item = mItems->getItem(experience[LLExperienceCache::EXPERIENCE_ID]);
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
std::string experience_name_string = experience[LLExperienceCache::NAME].asString();
|
||||
if (experience_name_string.empty())
|
||||
{
|
||||
experience_name_string = LLTrans::getString("ExperienceNameUntitled");
|
||||
}
|
||||
|
||||
item->getColumn(0)->setValue(experience_name_string);
|
||||
}
|
||||
|
||||
LLPanelExperienceListEditor::~LLPanelExperienceListEditor()
|
||||
{
|
||||
if(!mPicker.isDead())
|
||||
{
|
||||
mPicker.get()->closeFloater();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::loading()
|
||||
{
|
||||
mItems->clear();
|
||||
mItems->setCommentText( getString("loading"));
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::setReadonly( bool val )
|
||||
{
|
||||
mReadonly = val;
|
||||
checkButtonsEnabled();
|
||||
}
|
||||
|
||||
void LLPanelExperienceListEditor::refreshExperienceCounter()
|
||||
{
|
||||
if(mMaxExperienceIDs > 0)
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[EXPERIENCES]"] = llformat("%d", mItems->getItemCount());
|
||||
args["[MAXEXPERIENCES]"] = llformat("%d", mMaxExperienceIDs);
|
||||
getChild<LLTextBox>("text_count")->setText(LLTrans::getString("ExperiencesCounter", args));
|
||||
}
|
||||
}
|
||||
|
||||
boost::signals2::connection LLPanelExperienceListEditor::setAddedCallback( list_changed_signal_t::slot_type cb )
|
||||
{
|
||||
return mAddedCallback.connect(cb);
|
||||
}
|
||||
|
||||
boost::signals2::connection LLPanelExperienceListEditor::setRemovedCallback( list_changed_signal_t::slot_type cb )
|
||||
{
|
||||
return mRemovedCallback.connect(cb);
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* @file llpanelexperiencelisteditor.cpp
|
||||
* @brief Editor for building a list of experiences
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&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_LLPANELEXPERIENCELISTEDITOR_H
|
||||
#define LL_LLPANELEXPERIENCELISTEDITOR_H
|
||||
|
||||
#include "llpanel.h"
|
||||
#include "lluuid.h"
|
||||
#include <set>
|
||||
|
||||
class LLScrollListCtrl;
|
||||
class LLButton;
|
||||
class LLFloaterExperiencePicker;
|
||||
|
||||
class LLPanelExperienceListEditor : public LLPanel
|
||||
{
|
||||
public:
|
||||
|
||||
typedef boost::signals2::signal<void (const LLUUID&) > list_changed_signal_t;
|
||||
// filter function for experiences, return true if the experience should be hidden.
|
||||
typedef boost::function<bool (const LLSD&)> experience_function;
|
||||
typedef std::vector<experience_function> filter_list;
|
||||
typedef LLHandle<LLFloaterExperiencePicker> PickerHandle;
|
||||
LLPanelExperienceListEditor();
|
||||
~LLPanelExperienceListEditor();
|
||||
BOOL postBuild();
|
||||
|
||||
void loading();
|
||||
|
||||
const uuid_list_t& getExperienceIds()const;
|
||||
void setExperienceIds(const LLSD& experience_ids);
|
||||
void addExperienceIds(const uuid_vec_t& experience_ids);
|
||||
|
||||
void addExperience(const LLUUID& id);
|
||||
|
||||
boost::signals2::connection setAddedCallback(list_changed_signal_t::slot_type cb );
|
||||
boost::signals2::connection setRemovedCallback(list_changed_signal_t::slot_type cb );
|
||||
|
||||
bool getReadonly() const { return mReadonly; }
|
||||
void setReadonly(bool val);
|
||||
|
||||
void refreshExperienceCounter();
|
||||
|
||||
void addFilter(experience_function func){mFilters.push_back(func);}
|
||||
void setStickyFunction(experience_function func){mSticky = func;}
|
||||
U32 getMaxExperienceIDs() const { return mMaxExperienceIDs; }
|
||||
void setMaxExperienceIDs(U32 val) { mMaxExperienceIDs = val; }
|
||||
private:
|
||||
|
||||
void onItems();
|
||||
void onRemove();
|
||||
void onAdd();
|
||||
void onProfile();
|
||||
|
||||
void checkButtonsEnabled();
|
||||
static void experienceDetailsCallback( LLHandle<LLPanelExperienceListEditor> panel, const LLSD& experience );
|
||||
void onExperienceDetails( const LLSD& experience );
|
||||
void processResponse( const LLSD& content );
|
||||
uuid_list_t mExperienceIds;
|
||||
|
||||
|
||||
LLScrollListCtrl* mItems;
|
||||
filter_list mFilters;
|
||||
LLButton* mAdd;
|
||||
LLButton* mRemove;
|
||||
LLButton* mProfile;
|
||||
PickerHandle mPicker;
|
||||
list_changed_signal_t mAddedCallback;
|
||||
list_changed_signal_t mRemovedCallback;
|
||||
LLUUID mKey;
|
||||
bool mReadonly;
|
||||
experience_function mSticky;
|
||||
U32 mMaxExperienceIDs;
|
||||
|
||||
};
|
||||
|
||||
#endif //LL_LLPANELEXPERIENCELISTEDITOR_H
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
/**
|
||||
* @file llpanelexperiencelog.cpp
|
||||
* @brief llpanelexperiencelog
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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 "llpanelexperiencelog.h"
|
||||
|
||||
#include "llexperiencelog.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llbutton.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llspinctrl.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterreporter.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
|
||||
|
||||
#define BTN_PROFILE_XP "btn_profile_xp"
|
||||
#define BTN_REPORT_XP "btn_report_xp"
|
||||
|
||||
static LLPanelInjector<LLPanelExperienceLog> register_experiences_panel("experience_log");
|
||||
|
||||
|
||||
LLPanelExperienceLog::LLPanelExperienceLog( )
|
||||
: mEventList(NULL)
|
||||
, mPageSize(25)
|
||||
, mCurrentPage(0)
|
||||
{
|
||||
buildFromFile("panel_experience_log.xml");
|
||||
}
|
||||
|
||||
|
||||
BOOL LLPanelExperienceLog::postBuild( void )
|
||||
{
|
||||
LLExperienceLog* log = LLExperienceLog::getInstance();
|
||||
mEventList = getChild<LLScrollListCtrl>("experience_log_list");
|
||||
mEventList->setCommitCallback(boost::bind(&LLPanelExperienceLog::onSelectionChanged, this));
|
||||
mEventList->setDoubleClickCallback( boost::bind(&LLPanelExperienceLog::onProfileExperience, this));
|
||||
|
||||
getChild<LLButton>("btn_clear")->setCommitCallback(boost::bind(&LLExperienceLog::clear, log));
|
||||
getChild<LLButton>("btn_clear")->setCommitCallback(boost::bind(&LLPanelExperienceLog::refresh, this));
|
||||
|
||||
getChild<LLButton>(BTN_PROFILE_XP)->setCommitCallback(boost::bind(&LLPanelExperienceLog::onProfileExperience, this));
|
||||
getChild<LLButton>(BTN_REPORT_XP )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onReportExperience, this));
|
||||
getChild<LLButton>("btn_notify" )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onNotify, this));
|
||||
getChild<LLButton>("btn_next" )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onNext, this));
|
||||
getChild<LLButton>("btn_prev" )->setCommitCallback(boost::bind(&LLPanelExperienceLog::onPrev, this));
|
||||
|
||||
LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("notify_all");
|
||||
check->set(log->getNotifyNewEvent());
|
||||
check->setCommitCallback(boost::bind(&LLPanelExperienceLog::notifyChanged, this));
|
||||
|
||||
|
||||
LLSpinCtrl* spin = getChild<LLSpinCtrl>("logsizespinner");
|
||||
spin->set(log->getMaxDays());
|
||||
spin->setCommitCallback(boost::bind(&LLPanelExperienceLog::logSizeChanged, this));
|
||||
|
||||
mPageSize = log->getPageSize();
|
||||
refresh();
|
||||
mNewEvent = LLExperienceLog::instance().addUpdateSignal(boost::bind(&LLPanelExperienceLog::refresh, this));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LLPanelExperienceLog* LLPanelExperienceLog::create()
|
||||
{
|
||||
return new LLPanelExperienceLog();
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::refresh()
|
||||
{
|
||||
S32 selected = mEventList->getFirstSelectedIndex();
|
||||
mEventList->deleteAllItems();
|
||||
const LLSD events = LLExperienceLog::instance().getEvents();
|
||||
|
||||
if(events.size() == 0)
|
||||
{
|
||||
mEventList->setCommentText(getString("no_events"));
|
||||
return;
|
||||
}
|
||||
|
||||
setAllChildrenEnabled(FALSE);
|
||||
|
||||
LLSD item;
|
||||
bool waiting = false;
|
||||
LLUUID waiting_id;
|
||||
|
||||
int itemsToSkip = mPageSize*mCurrentPage;
|
||||
int items = 0;
|
||||
bool moreItems = false;
|
||||
|
||||
if (!events.emptyMap())
|
||||
{
|
||||
LLSD::map_const_iterator day = events.endMap();
|
||||
do
|
||||
{
|
||||
--day;
|
||||
const LLSD& dayArray = day->second;
|
||||
int size = dayArray.size();
|
||||
if(itemsToSkip > size)
|
||||
{
|
||||
itemsToSkip -= size;
|
||||
continue;
|
||||
}
|
||||
if(items >= mPageSize && size > 0)
|
||||
{
|
||||
moreItems = true;
|
||||
break;
|
||||
}
|
||||
for(int i = dayArray.size() - itemsToSkip - 1; i >= 0; i--)
|
||||
{
|
||||
if(items >= mPageSize)
|
||||
{
|
||||
moreItems = true;
|
||||
break;
|
||||
}
|
||||
const LLSD event = dayArray[i];
|
||||
LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
const LLSD& experience = LLExperienceCache::get(id);
|
||||
if(experience.isUndefined()){
|
||||
waiting = true;
|
||||
waiting_id = id;
|
||||
}
|
||||
if(!waiting)
|
||||
{
|
||||
item["id"] = event;
|
||||
|
||||
LLSD& columns = item["columns"];
|
||||
columns[0]["column"] = "time";
|
||||
columns[0]["value"] = day->first+event["Time"].asString();
|
||||
columns[1]["column"] = "event";
|
||||
columns[1]["value"] = LLExperienceLog::getPermissionString(event, "ExperiencePermissionShort");
|
||||
columns[2]["column"] = "experience_name";
|
||||
columns[2]["value"] = experience[LLExperienceCache::NAME].asString();
|
||||
columns[3]["column"] = "object_name";
|
||||
columns[3]["value"] = event["ObjectName"].asString();
|
||||
mEventList->addElement(item);
|
||||
}
|
||||
++items;
|
||||
}
|
||||
} while (day != events.beginMap());
|
||||
}
|
||||
if(waiting)
|
||||
{
|
||||
mEventList->deleteAllItems();
|
||||
mEventList->setCommentText(getString("loading"));
|
||||
LLExperienceCache::get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
setAllChildrenEnabled(TRUE);
|
||||
|
||||
mEventList->setEnabled(TRUE);
|
||||
getChild<LLButton>("btn_next")->setEnabled(moreItems);
|
||||
getChild<LLButton>("btn_prev")->setEnabled(mCurrentPage>0);
|
||||
getChild<LLButton>("btn_clear")->setEnabled(mEventList->getItemCount()>0);
|
||||
if(selected<0)
|
||||
{
|
||||
selected = 0;
|
||||
}
|
||||
mEventList->selectNthItem(selected);
|
||||
onSelectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::onProfileExperience()
|
||||
{
|
||||
LLSD event = getSelectedEvent();
|
||||
if(event.isDefined())
|
||||
{
|
||||
LLFloaterReg::showInstance("experience_profile", event[LLExperienceCache::EXPERIENCE_ID].asUUID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::onReportExperience()
|
||||
{
|
||||
LLSD event = getSelectedEvent();
|
||||
if(event.isDefined())
|
||||
{
|
||||
LLFloaterReporter::showFromExperience(event[LLExperienceCache::EXPERIENCE_ID].asUUID());
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::onNotify()
|
||||
{
|
||||
LLSD event = getSelectedEvent();
|
||||
if(event.isDefined())
|
||||
{
|
||||
LLExperienceLog::instance().notify(event);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::onNext()
|
||||
{
|
||||
mCurrentPage++;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::onPrev()
|
||||
{
|
||||
if(mCurrentPage>0)
|
||||
{
|
||||
mCurrentPage--;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::notifyChanged()
|
||||
{
|
||||
LLExperienceLog::instance().setNotifyNewEvent(getChild<LLCheckBoxCtrl>("notify_all")->get());
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::logSizeChanged()
|
||||
{
|
||||
int value = (int)(getChild<LLSpinCtrl>("logsizespinner")->get());
|
||||
bool dirty = value > 0 && value < LLExperienceLog::instance().getMaxDays();
|
||||
LLExperienceLog::instance().setMaxDays(value);
|
||||
if(dirty)
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperienceLog::onSelectionChanged()
|
||||
{
|
||||
bool enabled = (1 == mEventList->getNumSelected());
|
||||
getChild<LLButton>(BTN_REPORT_XP)->setEnabled(enabled);
|
||||
getChild<LLButton>(BTN_PROFILE_XP)->setEnabled(enabled);
|
||||
getChild<LLButton>("btn_notify")->setEnabled(enabled);
|
||||
}
|
||||
|
||||
LLSD LLPanelExperienceLog::getSelectedEvent()
|
||||
{
|
||||
LLScrollListItem* item = mEventList->getFirstSelected();
|
||||
if(item)
|
||||
{
|
||||
return item->getValue();
|
||||
}
|
||||
return LLSD();
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file llpanelexperiencelog.h
|
||||
* @brief llpanelexperiencelog and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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_LLPANELEXPERIENCELOG_H
|
||||
#define LL_LLPANELEXPERIENCELOG_H
|
||||
|
||||
#include "llpanel.h"
|
||||
class LLScrollListCtrl;
|
||||
|
||||
class LLPanelExperienceLog
|
||||
: public LLPanel
|
||||
{
|
||||
public:
|
||||
|
||||
LLPanelExperienceLog();
|
||||
|
||||
static LLPanelExperienceLog* create();
|
||||
|
||||
/*virtual*/ BOOL postBuild(void);
|
||||
|
||||
void refresh();
|
||||
protected:
|
||||
void logSizeChanged();
|
||||
void notifyChanged();
|
||||
void onNext();
|
||||
void onNotify();
|
||||
void onPrev();
|
||||
void onProfileExperience();
|
||||
void onReportExperience();
|
||||
void onSelectionChanged();
|
||||
|
||||
LLSD getSelectedEvent();
|
||||
private:
|
||||
LLScrollListCtrl* mEventList;
|
||||
U32 mPageSize;
|
||||
U32 mCurrentPage;
|
||||
boost::signals2::scoped_connection mNewEvent;
|
||||
};
|
||||
|
||||
#endif // LL_LLPANELEXPERIENCELOG_H
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
/**
|
||||
* @file llpanelexperiencepicker.cpp
|
||||
* @brief Implementation of llpanelexperiencepicker
|
||||
* @author dolphin@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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 "llpanelexperiencepicker.h"
|
||||
|
||||
|
||||
#include "lllineeditor.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llagent.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llslurl.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llfloater.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
#define BTN_FIND "find"
|
||||
#define BTN_OK "ok_btn"
|
||||
#define BTN_CANCEL "cancel_btn"
|
||||
#define BTN_PROFILE "profile_btn"
|
||||
#define BTN_LEFT "left_btn"
|
||||
#define BTN_RIGHT "right_btn"
|
||||
#define TEXT_EDIT "edit"
|
||||
#define TEXT_MATURITY "maturity"
|
||||
#define LIST_RESULTS "search_results"
|
||||
#define PANEL_SEARCH "search_panel"
|
||||
|
||||
const static std::string columnSpace = " ";
|
||||
|
||||
static LLPanelInjector<LLPanelExperiencePicker> t_panel_status("llpanelexperiencepicker");
|
||||
|
||||
class LLExperienceSearchResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
LLUUID mQueryID;
|
||||
LLHandle<LLPanelExperiencePicker> mParent;
|
||||
|
||||
LLExperienceSearchResponder(const LLUUID& id, const LLHandle<LLPanelExperiencePicker>& parent) : mQueryID(id), mParent(parent) { }
|
||||
|
||||
protected:
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
if(mParent.isDead())
|
||||
return;
|
||||
|
||||
LLPanelExperiencePicker* panel =mParent.get();
|
||||
if (panel)
|
||||
{
|
||||
panel->processResponse(mQueryID, getContent());
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
if(mParent.isDead())
|
||||
return;
|
||||
|
||||
LLPanelExperiencePicker* panel =mParent.get();
|
||||
if (panel)
|
||||
{
|
||||
panel->processResponse(mQueryID, LLSD());
|
||||
}
|
||||
LL_WARNS() << "experience picker failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
|
||||
}
|
||||
};
|
||||
|
||||
LLPanelExperiencePicker::LLPanelExperiencePicker()
|
||||
:LLPanel()
|
||||
{
|
||||
buildFromFile("panel_experience_search.xml");
|
||||
setDefaultFilters();
|
||||
}
|
||||
|
||||
LLPanelExperiencePicker::~LLPanelExperiencePicker()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLPanelExperiencePicker::postBuild()
|
||||
{
|
||||
getChild<LLLineEditor>(TEXT_EDIT)->setKeystrokeCallback( boost::bind(&LLPanelExperiencePicker::editKeystroke, this, _1, _2),NULL);
|
||||
|
||||
childSetAction(BTN_FIND, boost::bind(&LLPanelExperiencePicker::onBtnFind, this));
|
||||
getChildView(BTN_FIND)->setEnabled(TRUE);
|
||||
|
||||
LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>(LIST_RESULTS);
|
||||
searchresults->setDoubleClickCallback( boost::bind(&LLPanelExperiencePicker::onBtnSelect, this));
|
||||
searchresults->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onList, this));
|
||||
getChildView(LIST_RESULTS)->setEnabled(FALSE);
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("no_results"));
|
||||
|
||||
childSetAction(BTN_OK, boost::bind(&LLPanelExperiencePicker::onBtnSelect, this));
|
||||
getChildView(BTN_OK)->setEnabled(FALSE);
|
||||
childSetAction(BTN_CANCEL, boost::bind(&LLPanelExperiencePicker::onBtnClose, this));
|
||||
childSetAction(BTN_PROFILE, boost::bind(&LLPanelExperiencePicker::onBtnProfile, this));
|
||||
getChildView(BTN_PROFILE)->setEnabled(FALSE);
|
||||
|
||||
getChild<LLComboBox>(TEXT_MATURITY)->setCurrentByIndex(2);
|
||||
getChild<LLComboBox>(TEXT_MATURITY)->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onMaturity, this));
|
||||
getChild<LLUICtrl>(TEXT_EDIT)->setFocus(TRUE);
|
||||
|
||||
childSetAction(BTN_LEFT, boost::bind(&LLPanelExperiencePicker::onPage, this, -1));
|
||||
childSetAction(BTN_RIGHT, boost::bind(&LLPanelExperiencePicker::onPage, this, 1));
|
||||
|
||||
LLPanel* search_panel = getChild<LLPanel>(PANEL_SEARCH);
|
||||
if (search_panel)
|
||||
{
|
||||
// Start searching when Return is pressed in the line editor.
|
||||
search_panel->setDefaultBtn(BTN_FIND);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::editKeystroke( class LLLineEditor* caller, void* user_data )
|
||||
{
|
||||
getChildView(BTN_FIND)->setEnabled(true);
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onBtnFind()
|
||||
{
|
||||
mCurrentPage=1;
|
||||
find();
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onList()
|
||||
{
|
||||
bool enabled = isSelectButtonEnabled();
|
||||
getChildView(BTN_OK)->setEnabled(enabled);
|
||||
|
||||
enabled = enabled && getChild<LLScrollListCtrl>(LIST_RESULTS)->getNumSelected() == 1;
|
||||
getChildView(BTN_PROFILE)->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::find()
|
||||
{
|
||||
std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
|
||||
mQueryID.generate();
|
||||
std::ostringstream url;
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
std::string cap = region->getCapability("FindExperienceByName");
|
||||
if (!cap.empty())
|
||||
{
|
||||
url << cap << "?page=" << mCurrentPage << "&page_size=30&query=" << LLURI::escape(text);
|
||||
LLHTTPClient::get(url.str(), new LLExperienceSearchResponder(mQueryID, getDerivedHandle<LLPanelExperiencePicker>()));
|
||||
|
||||
}
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
|
||||
|
||||
getChildView(BTN_OK)->setEnabled(FALSE);
|
||||
getChildView(BTN_PROFILE)->setEnabled(FALSE);
|
||||
|
||||
getChildView(BTN_RIGHT)->setEnabled(FALSE);
|
||||
getChildView(BTN_LEFT)->setEnabled(FALSE);
|
||||
}
|
||||
|
||||
|
||||
bool LLPanelExperiencePicker::isSelectButtonEnabled()
|
||||
{
|
||||
LLScrollListCtrl* list=getChild<LLScrollListCtrl>(LIST_RESULTS);
|
||||
return list->getFirstSelectedIndex() >=0;
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids )
|
||||
{
|
||||
std::vector<LLScrollListItem*> items = results->getAllSelected();
|
||||
for(std::vector<LLScrollListItem*>::iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
LLScrollListItem* item = *it;
|
||||
if (item->getUUID().notNull())
|
||||
{
|
||||
experience_ids.push_back(item->getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::setAllowMultiple( bool allow_multiple )
|
||||
{
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->setAllowMultipleSelection(allow_multiple);
|
||||
}
|
||||
|
||||
|
||||
void name_callback(const LLHandle<LLPanelExperiencePicker>& floater, const LLUUID& experience_id, const LLUUID& agent_id, const LLAvatarName& av_name)
|
||||
{
|
||||
if(floater.isDead())
|
||||
return;
|
||||
LLPanelExperiencePicker* picker = floater.get();
|
||||
LLScrollListCtrl* search_results = picker->getChild<LLScrollListCtrl>(LIST_RESULTS);
|
||||
|
||||
LLScrollListItem* item = search_results->getItem(experience_id);
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
item->getColumn(2)->setValue(columnSpace+av_name.getDisplayName());
|
||||
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLSD& content )
|
||||
{
|
||||
if(query_id != mQueryID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResponse = content;
|
||||
|
||||
const LLSD& experiences=mResponse["experience_keys"];
|
||||
LLSD::array_const_iterator it = experiences.beginArray();
|
||||
for ( ; it != experiences.endArray(); ++it)
|
||||
{
|
||||
LLExperienceCache::insert(*it);
|
||||
}
|
||||
|
||||
getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url"));
|
||||
getChildView(BTN_LEFT)->setEnabled(content.has("previous_page_url"));
|
||||
|
||||
filterContent();
|
||||
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onBtnSelect()
|
||||
{
|
||||
if(!isSelectButtonEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(mSelectionCallback)
|
||||
{
|
||||
const LLScrollListCtrl* results = getChild<LLScrollListCtrl>(LIST_RESULTS);
|
||||
uuid_vec_t experience_ids;
|
||||
|
||||
getSelectedExperienceIds(results, experience_ids);
|
||||
mSelectionCallback(experience_ids);
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->deselectAllItems(TRUE);
|
||||
if(mCloseOnSelect)
|
||||
{
|
||||
mCloseOnSelect = FALSE;
|
||||
onBtnClose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
onBtnProfile();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onBtnClose()
|
||||
{
|
||||
LLFloater* floater = getParentByType<LLFloater>();
|
||||
if (floater)
|
||||
{
|
||||
floater->closeFloater();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onBtnProfile()
|
||||
{
|
||||
LLScrollListItem* item = getChild<LLScrollListCtrl>(LIST_RESULTS)->getFirstSelected();
|
||||
if(item)
|
||||
{
|
||||
LLFloaterReg::showInstance("experience_profile", item->getUUID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
std::string LLPanelExperiencePicker::getMaturityString(int maturity)
|
||||
{
|
||||
if(maturity <= SIM_ACCESS_PG)
|
||||
{
|
||||
return getString("maturity_icon_general");
|
||||
}
|
||||
else if(maturity <= SIM_ACCESS_MATURE)
|
||||
{
|
||||
return getString("maturity_icon_moderate");
|
||||
}
|
||||
return getString("maturity_icon_adult");
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::filterContent()
|
||||
{
|
||||
LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>(LIST_RESULTS);
|
||||
|
||||
const LLSD& experiences=mResponse["experience_keys"];
|
||||
|
||||
search_results->deleteAllItems();
|
||||
|
||||
LLSD item;
|
||||
LLSD::array_const_iterator it = experiences.beginArray();
|
||||
for ( ; it != experiences.endArray(); ++it)
|
||||
{
|
||||
const LLSD& experience = *it;
|
||||
|
||||
if(isExperienceHidden(experience))
|
||||
continue;
|
||||
|
||||
std::string experience_name_string = experience[LLExperienceCache::NAME].asString();
|
||||
if (experience_name_string.empty())
|
||||
{
|
||||
experience_name_string = LLTrans::getString("ExperienceNameUntitled");
|
||||
}
|
||||
|
||||
item["id"]=experience[LLExperienceCache::EXPERIENCE_ID];
|
||||
LLSD& columns = item["columns"];
|
||||
columns[0]["column"] = "maturity";
|
||||
columns[0]["value"] = getMaturityString(experience[LLExperienceCache::MATURITY].asInteger());
|
||||
columns[0]["type"]="icon";
|
||||
columns[0]["halign"]="right";
|
||||
columns[1]["column"] = "experience_name";
|
||||
columns[1]["value"] = columnSpace+experience_name_string;
|
||||
columns[2]["column"] = "owner";
|
||||
columns[2]["value"] = columnSpace+getString("loading");
|
||||
search_results->addElement(item);
|
||||
LLAvatarNameCache::get(experience[LLExperienceCache::AGENT_ID], boost::bind(name_callback, getDerivedHandle<LLPanelExperiencePicker>(), experience[LLExperienceCache::EXPERIENCE_ID], _1, _2));
|
||||
}
|
||||
|
||||
if (search_results->isEmpty())
|
||||
{
|
||||
LLStringUtil::format_map_t map;
|
||||
std::string search_text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
|
||||
map["[TEXT]"] = search_text;
|
||||
if (search_text.empty())
|
||||
{
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("no_results"));
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("not_found", map));
|
||||
}
|
||||
search_results->setEnabled(false);
|
||||
getChildView(BTN_OK)->setEnabled(false);
|
||||
getChildView(BTN_PROFILE)->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
getChildView(BTN_OK)->setEnabled(true);
|
||||
search_results->setEnabled(true);
|
||||
search_results->sortByColumnIndex(1, TRUE);
|
||||
std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
|
||||
if (!search_results->selectItemByLabel(text, TRUE, 1))
|
||||
{
|
||||
search_results->selectFirstItem();
|
||||
}
|
||||
onList();
|
||||
search_results->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onMaturity()
|
||||
{
|
||||
if(mResponse.has("experience_keys") && mResponse["experience_keys"].beginArray() != mResponse["experience_keys"].endArray())
|
||||
{
|
||||
filterContent();
|
||||
}
|
||||
}
|
||||
|
||||
bool LLPanelExperiencePicker::isExperienceHidden( const LLSD& experience) const
|
||||
{
|
||||
bool hide=false;
|
||||
filter_list::const_iterator it = mFilters.begin();
|
||||
for(/**/;it != mFilters.end(); ++it)
|
||||
{
|
||||
if((*it)(experience)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return hide;
|
||||
}
|
||||
|
||||
bool LLPanelExperiencePicker::FilterOverRating( const LLSD& experience )
|
||||
{
|
||||
int maturity = getChild<LLComboBox>(TEXT_MATURITY)->getSelectedValue().asInteger();
|
||||
return experience[LLExperienceCache::MATURITY].asInteger() > maturity;
|
||||
}
|
||||
|
||||
bool LLPanelExperiencePicker::FilterWithProperty( const LLSD& experience, S32 prop)
|
||||
{
|
||||
return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) != 0;
|
||||
}
|
||||
|
||||
bool LLPanelExperiencePicker::FilterWithoutProperties( const LLSD& experience, S32 prop)
|
||||
{
|
||||
return ((experience[LLExperienceCache::PROPERTIES].asInteger() & prop) == prop);
|
||||
}
|
||||
|
||||
bool LLPanelExperiencePicker::FilterWithoutProperty( const LLSD& experience, S32 prop )
|
||||
{
|
||||
return (experience[LLExperienceCache::PROPERTIES].asInteger() & prop) == 0;
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::setDefaultFilters()
|
||||
{
|
||||
mFilters.clear();
|
||||
addFilter(boost::bind(&LLPanelExperiencePicker::FilterOverRating, this, _1));
|
||||
}
|
||||
|
||||
bool LLPanelExperiencePicker::FilterMatching( const LLSD& experience, const LLUUID& id )
|
||||
{
|
||||
if(experience.isUUID())
|
||||
{
|
||||
return experience.asUUID() == id;
|
||||
}
|
||||
return experience[LLExperienceCache::EXPERIENCE_ID].asUUID() == id;
|
||||
}
|
||||
|
||||
void LLPanelExperiencePicker::onPage( S32 direction )
|
||||
{
|
||||
mCurrentPage += direction;
|
||||
if(mCurrentPage < 1)
|
||||
{
|
||||
mCurrentPage = 1;
|
||||
}
|
||||
find();
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* @file llpanelexperiencepicker.h
|
||||
* @brief Header file for llpanelexperiencepicker
|
||||
* @author dolphin@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, 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_LLPANELEXPERIENCEPICKER_H
|
||||
#define LL_LLPANELEXPERIENCEPICKER_H
|
||||
|
||||
#include "llpanel.h"
|
||||
|
||||
class LLScrollListCtrl;
|
||||
class LLLineEditor;
|
||||
|
||||
|
||||
class LLPanelExperiencePicker : public LLPanel
|
||||
{
|
||||
public:
|
||||
friend class LLExperienceSearchResponder;
|
||||
friend class LLFloaterExperiencePicker;
|
||||
|
||||
typedef boost::function<void (const uuid_vec_t&)> select_callback_t;
|
||||
// filter function for experiences, return true if the experience should be hidden.
|
||||
typedef boost::function<bool (const LLSD&)> filter_function;
|
||||
typedef std::vector<filter_function> filter_list;
|
||||
|
||||
LLPanelExperiencePicker();
|
||||
virtual ~LLPanelExperiencePicker();
|
||||
|
||||
BOOL postBuild();
|
||||
|
||||
void addFilter(filter_function func){mFilters.push_back(func);}
|
||||
template <class IT>
|
||||
void addFilters(IT begin, IT end){mFilters.insert(mFilters.end(), begin, end);}
|
||||
void setDefaultFilters();
|
||||
|
||||
static bool FilterWithProperty(const LLSD& experience, S32 prop);
|
||||
static bool FilterWithoutProperties(const LLSD& experience, S32 prop);
|
||||
static bool FilterWithoutProperty(const LLSD& experience, S32 prop);
|
||||
static bool FilterMatching(const LLSD& experience, const LLUUID& id);
|
||||
bool FilterOverRating(const LLSD& experience);
|
||||
|
||||
private:
|
||||
void editKeystroke(LLLineEditor* caller, void* user_data);
|
||||
|
||||
void onBtnFind();
|
||||
void onBtnSelect();
|
||||
void onBtnClose();
|
||||
void onBtnProfile();
|
||||
void onList();
|
||||
void onMaturity();
|
||||
void onPage(S32 direction);
|
||||
|
||||
void getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids );
|
||||
void setAllowMultiple(bool allow_multiple);
|
||||
|
||||
|
||||
void find();
|
||||
bool isSelectButtonEnabled();
|
||||
void processResponse( const LLUUID& query_id, const LLSD& content );
|
||||
|
||||
void filterContent();
|
||||
bool isExperienceHidden(const LLSD& experience) const ;
|
||||
std::string getMaturityString(int maturity);
|
||||
|
||||
|
||||
select_callback_t mSelectionCallback;
|
||||
filter_list mFilters;
|
||||
LLUUID mQueryID;
|
||||
LLSD mResponse;
|
||||
bool mCloseOnSelect;
|
||||
S32 mCurrentPage;
|
||||
};
|
||||
|
||||
#endif // LL_LLPANELEXPERIENCEPICKER_H
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* @file llpanelexperiences.cpp
|
||||
* @brief LLPanelExperiences class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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 "llpanelprofile.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llagent.h"
|
||||
|
||||
#include "llpanelexperiences.h"
|
||||
#include "llslurl.h"
|
||||
#include "lllayoutstack.h"
|
||||
|
||||
|
||||
|
||||
static LLPanelInjector<LLPanelExperiences> register_experiences_panel("experiences_panel");
|
||||
|
||||
|
||||
//comparators
|
||||
static const LLExperienceItemComparator NAME_COMPARATOR;
|
||||
|
||||
LLPanelExperiences::LLPanelExperiences( )
|
||||
: mExperiencesList(NULL)
|
||||
{
|
||||
buildFromFile("panel_experiences.xml");
|
||||
}
|
||||
|
||||
BOOL LLPanelExperiences::postBuild( void )
|
||||
{
|
||||
mExperiencesList = getChild<LLFlatListView>("experiences_list");
|
||||
if (hasString("loading_experiences"))
|
||||
{
|
||||
mExperiencesList->setNoItemsCommentText(getString("loading_experiences"));
|
||||
}
|
||||
else if (hasString("no_experiences"))
|
||||
{
|
||||
mExperiencesList->setNoItemsCommentText(getString("no_experiences"));
|
||||
}
|
||||
mExperiencesList->setComparator(&NAME_COMPARATOR);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLExperienceItem* LLPanelExperiences::getSelectedExperienceItem()
|
||||
{
|
||||
LLPanel* selected_item = mExperiencesList->getSelectedItem();
|
||||
if (!selected_item) return NULL;
|
||||
|
||||
return dynamic_cast<LLExperienceItem*>(selected_item);
|
||||
}
|
||||
|
||||
void LLPanelExperiences::setExperienceList( const LLSD& experiences )
|
||||
{
|
||||
if (hasString("no_experiences"))
|
||||
{
|
||||
mExperiencesList->setNoItemsCommentText(getString("no_experiences"));
|
||||
}
|
||||
mExperiencesList->clear();
|
||||
|
||||
LLSD::array_const_iterator it = experiences.beginArray();
|
||||
for( /**/ ; it != experiences.endArray(); ++it)
|
||||
{
|
||||
LLUUID public_key = it->asUUID();
|
||||
LLExperienceItem* item = new LLExperienceItem();
|
||||
|
||||
item->init(public_key);
|
||||
mExperiencesList->addItem(item, public_key);
|
||||
}
|
||||
|
||||
mExperiencesList->sort();
|
||||
}
|
||||
|
||||
LLPanelExperiences* LLPanelExperiences::create(const std::string& name)
|
||||
{
|
||||
LLPanelExperiences* panel= new LLPanelExperiences();
|
||||
panel->setName(name);
|
||||
return panel;
|
||||
}
|
||||
|
||||
void LLPanelExperiences::removeExperiences( const LLSD& ids )
|
||||
{
|
||||
LLSD::array_const_iterator it = ids.beginArray();
|
||||
for( /**/ ; it != ids.endArray(); ++it)
|
||||
{
|
||||
removeExperience(it->asUUID());
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiences::removeExperience( const LLUUID& id )
|
||||
{
|
||||
mExperiencesList->removeItemByUUID(id);
|
||||
}
|
||||
|
||||
void LLPanelExperiences::addExperience( const LLUUID& id )
|
||||
{
|
||||
if(!mExperiencesList->getItemByValue(id))
|
||||
{
|
||||
LLExperienceItem* item = new LLExperienceItem();
|
||||
|
||||
item->init(id);
|
||||
mExperiencesList->addItem(item, id);
|
||||
mExperiencesList->sort();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiences::setButtonAction(const std::string& label, const commit_signal_t::slot_type& cb )
|
||||
{
|
||||
if(label.empty())
|
||||
{
|
||||
getChild<LLLayoutPanel>("button_panel")->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild<LLLayoutPanel>("button_panel")->setVisible(true);
|
||||
LLButton* child = getChild<LLButton>("btn_action");
|
||||
child->setCommitCallback(cb);
|
||||
child->setLabel(getString(label));
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelExperiences::enableButton( bool enable )
|
||||
{
|
||||
getChild<LLButton>("btn_action")->setEnabled(enable);
|
||||
}
|
||||
|
||||
|
||||
LLExperienceItem::LLExperienceItem()
|
||||
: mName(NULL)
|
||||
{
|
||||
buildFromFile("panel_experience_list_item.xml");
|
||||
}
|
||||
|
||||
void LLExperienceItem::init( const LLUUID& id)
|
||||
{
|
||||
mName = getChild<LLUICtrl>("experience_name");
|
||||
mName->setValue(LLSLURL("experience", id, "profile").getSLURLString());
|
||||
}
|
||||
|
||||
LLExperienceItem::~LLExperienceItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string LLExperienceItem::getExperienceName() const
|
||||
{
|
||||
if (mName)
|
||||
{
|
||||
return mName->getValue();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void LLPanelSearchExperiences::doSearch()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LLPanelSearchExperiences* LLPanelSearchExperiences::create( const std::string& name )
|
||||
{
|
||||
LLPanelSearchExperiences* panel= new LLPanelSearchExperiences();
|
||||
panel->getChild<LLPanel>("results")->addChild(LLPanelExperiences::create(name));
|
||||
return panel;
|
||||
}
|
||||
|
||||
BOOL LLPanelSearchExperiences::postBuild( void )
|
||||
{
|
||||
childSetAction("search_button", boost::bind(&LLPanelSearchExperiences::doSearch, this));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool LLExperienceItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
|
||||
{
|
||||
const LLExperienceItem* experience_item1 = dynamic_cast<const LLExperienceItem*>(item1);
|
||||
const LLExperienceItem* experience_item2 = dynamic_cast<const LLExperienceItem*>(item2);
|
||||
|
||||
if (!experience_item1 || !experience_item2)
|
||||
{
|
||||
LL_ERRS() << "item1 and item2 cannot be null" << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string name1 = experience_item1->getExperienceName();
|
||||
std::string name2 = experience_item2->getExperienceName();
|
||||
|
||||
LLStringUtil::toUpper(name1);
|
||||
LLStringUtil::toUpper(name2);
|
||||
|
||||
return name1 < name2;
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* @file llpanelexperiences.h
|
||||
* @brief LLPanelExperiences class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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_LLPANELEXPERIENCES_H
|
||||
#define LL_LLPANELEXPERIENCES_H
|
||||
|
||||
#include "llaccordionctrltab.h"
|
||||
#include "llflatlistview.h"
|
||||
#include "llpanelavatar.h"
|
||||
|
||||
class LLExperienceItem;
|
||||
class LLPanelProfile;
|
||||
|
||||
|
||||
class LLPanelSearchExperiences
|
||||
: public LLPanel
|
||||
{
|
||||
public:
|
||||
LLPanelSearchExperiences(){}
|
||||
static LLPanelSearchExperiences* create(const std::string& name);
|
||||
/*virtual*/ BOOL postBuild(void);
|
||||
|
||||
void doSearch();
|
||||
};
|
||||
|
||||
class LLPanelExperiences
|
||||
: public LLPanel
|
||||
{
|
||||
public:
|
||||
LLPanelExperiences();
|
||||
|
||||
static LLPanelExperiences* create(const std::string& name);
|
||||
|
||||
/*virtual*/ BOOL postBuild(void);
|
||||
/*virtual*/ void onClosePanel();
|
||||
|
||||
void setExperienceList(const LLSD& experiences);
|
||||
|
||||
LLExperienceItem* getSelectedExperienceItem();
|
||||
void removeExperiences( const LLSD& ids );
|
||||
void removeExperience( const LLUUID& id);
|
||||
void addExperience( const LLUUID& id);
|
||||
void setButtonAction(const std::string& label, const commit_signal_t::slot_type& cb);
|
||||
void enableButton(bool enable);
|
||||
protected:
|
||||
|
||||
private:
|
||||
LLFlatListView* mExperiencesList;
|
||||
};
|
||||
|
||||
class LLExperienceItemComparator : public LLFlatListView::ItemComparator
|
||||
{
|
||||
LOG_CLASS(LLExperienceItemComparator);
|
||||
|
||||
public:
|
||||
LLExperienceItemComparator() {};
|
||||
virtual ~LLExperienceItemComparator() {};
|
||||
|
||||
virtual bool compare(const LLPanel* item1, const LLPanel* item2) const;
|
||||
};
|
||||
|
||||
class LLExperienceItem
|
||||
: public LLPanel
|
||||
{
|
||||
public:
|
||||
LLExperienceItem();
|
||||
~LLExperienceItem();
|
||||
|
||||
void init(const LLUUID& experience_id);
|
||||
std::string getExperienceName() const;
|
||||
protected:
|
||||
LLUICtrl* mName;
|
||||
};
|
||||
#endif // LL_LLPANELEXPERIENCES_H
|
||||
|
|
@ -177,11 +177,13 @@ BOOL LLPanelGroup::postBuild()
|
|||
LLPanelGroupTab* panel_roles = findChild<LLPanelGroupTab>("group_roles_tab_panel");
|
||||
LLPanelGroupTab* panel_notices = findChild<LLPanelGroupTab>("group_notices_tab_panel");
|
||||
LLPanelGroupTab* panel_land = findChild<LLPanelGroupTab>("group_land_tab_panel");
|
||||
LLPanelGroupTab* panel_experiences = findChild<LLPanelGroupTab>("group_experiences_tab_panel");
|
||||
|
||||
if(panel_general) mTabs.push_back(panel_general);
|
||||
if(panel_roles) mTabs.push_back(panel_roles);
|
||||
if(panel_notices) mTabs.push_back(panel_notices);
|
||||
if(panel_land) mTabs.push_back(panel_land);
|
||||
if(panel_experiences) mTabs.push_back(panel_experiences);
|
||||
|
||||
if(panel_general)
|
||||
{
|
||||
|
|
@ -418,6 +420,7 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
|
|||
LLAccordionCtrlTab* tab_roles = getChild<LLAccordionCtrlTab>("group_roles_tab");
|
||||
LLAccordionCtrlTab* tab_notices = getChild<LLAccordionCtrlTab>("group_notices_tab");
|
||||
LLAccordionCtrlTab* tab_land = getChild<LLAccordionCtrlTab>("group_land_tab");
|
||||
LLAccordionCtrlTab* tab_experiences = getChild<LLAccordionCtrlTab>("group_experiences_tab");
|
||||
|
||||
if(mButtonJoin)
|
||||
mButtonJoin->setVisible(false);
|
||||
|
|
@ -434,10 +437,13 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
|
|||
tab_notices->changeOpenClose(tab_notices->getDisplayChildren());
|
||||
if(tab_land->getDisplayChildren())
|
||||
tab_land->changeOpenClose(tab_land->getDisplayChildren());
|
||||
if(tab_experiences->getDisplayChildren())
|
||||
tab_experiences->changeOpenClose(tab_land->getDisplayChildren());
|
||||
|
||||
tab_roles->setVisible(false);
|
||||
tab_notices->setVisible(false);
|
||||
tab_land->setVisible(false);
|
||||
tab_experiences->setVisible(false);
|
||||
|
||||
getChild<LLUICtrl>("group_name")->setVisible(false);
|
||||
getChild<LLUICtrl>("group_name_editor")->setVisible(true);
|
||||
|
|
@ -459,6 +465,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
|
|||
tab_notices->changeOpenClose(tab_notices->getDisplayChildren());
|
||||
if(tab_land->getDisplayChildren())
|
||||
tab_land->changeOpenClose(tab_land->getDisplayChildren());
|
||||
if(tab_experiences->getDisplayChildren())
|
||||
tab_experiences->changeOpenClose(tab_land->getDisplayChildren());
|
||||
}
|
||||
|
||||
LLGroupData agent_gdatap;
|
||||
|
|
@ -467,6 +475,7 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
|
|||
tab_roles->setVisible(is_member);
|
||||
tab_notices->setVisible(is_member);
|
||||
tab_land->setVisible(is_member);
|
||||
tab_experiences->setVisible(is_member);
|
||||
|
||||
getChild<LLUICtrl>("group_name")->setVisible(true);
|
||||
getChild<LLUICtrl>("group_name_editor")->setVisible(false);
|
||||
|
|
@ -534,6 +543,7 @@ bool LLPanelGroup::apply()
|
|||
&& apply(findChild<LLPanelGroupTab>("group_roles_tab_panel"))
|
||||
&& apply(findChild<LLPanelGroupTab>("group_notices_tab_panel"))
|
||||
&& apply(findChild<LLPanelGroupTab>("group_land_tab_panel"))
|
||||
&& apply(findChild<LLPanelGroupTab>("group_experiences_tab_panel"))
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* @file llpanelgroupexperiences.cpp
|
||||
* @brief List of experiences owned by a group.
|
||||
*
|
||||
* $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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llpanelgroupexperiences.h"
|
||||
|
||||
#include "lluictrlfactory.h"
|
||||
#include "roles_constants.h"
|
||||
|
||||
#include "llhttpclient.h"
|
||||
#include "llagent.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llflatlistview.h"
|
||||
#include "llpanelexperiences.h"
|
||||
#include "llsd.h"
|
||||
|
||||
|
||||
static LLPanelInjector<LLPanelGroupExperiences> t_panel_group_experiences("panel_group_experiences");
|
||||
|
||||
|
||||
class LLGroupExperienceResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
LLHandle<LLPanelGroupExperiences> mHandle;
|
||||
|
||||
LLGroupExperienceResponder(LLHandle<LLPanelGroupExperiences> handle) : mHandle(handle) { }
|
||||
|
||||
protected:
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
if (mHandle.isDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLPanelGroupExperiences* panel = mHandle.get();
|
||||
if (panel)
|
||||
{
|
||||
panel->setExperienceList(getContent().get("experience_ids"));
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
|
||||
}
|
||||
};
|
||||
|
||||
LLPanelGroupExperiences::LLPanelGroupExperiences()
|
||||
: LLPanelGroupTab(), mExperiencesList(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLPanelGroupExperiences::~LLPanelGroupExperiences()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLPanelGroupExperiences::postBuild()
|
||||
{
|
||||
mExperiencesList = getChild<LLFlatListView>("experiences_list");
|
||||
if (hasString("loading_experiences"))
|
||||
{
|
||||
mExperiencesList->setNoItemsCommentText(getString("loading_experiences"));
|
||||
}
|
||||
else if (hasString("no_experiences"))
|
||||
{
|
||||
mExperiencesList->setNoItemsCommentText(getString("no_experiences"));
|
||||
}
|
||||
|
||||
return LLPanelGroupTab::postBuild();
|
||||
}
|
||||
|
||||
void LLPanelGroupExperiences::activate()
|
||||
{
|
||||
if (getGroupID() == LLUUID::null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// search for experiences owned by the current group
|
||||
std::string url = gAgent.getRegion()->getCapability("GroupExperiences");
|
||||
if (!url.empty())
|
||||
{
|
||||
url += "?" + getGroupID().asString();
|
||||
|
||||
LLHTTPClient::get(url, new LLGroupExperienceResponder(getDerivedHandle<LLPanelGroupExperiences>()));
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelGroupExperiences::setGroupID(const LLUUID& id)
|
||||
{
|
||||
LLPanelGroupTab::setGroupID(id);
|
||||
|
||||
if(id == LLUUID::null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
activate();
|
||||
}
|
||||
|
||||
void LLPanelGroupExperiences::setExperienceList(const LLSD& experiences)
|
||||
{
|
||||
if (hasString("no_experiences"))
|
||||
{
|
||||
mExperiencesList->setNoItemsCommentText(getString("no_experiences"));
|
||||
}
|
||||
mExperiencesList->clear();
|
||||
|
||||
LLSD::array_const_iterator it = experiences.beginArray();
|
||||
for ( /**/ ; it != experiences.endArray(); ++it)
|
||||
{
|
||||
LLUUID public_key = it->asUUID();
|
||||
LLExperienceItem* item = new LLExperienceItem();
|
||||
|
||||
item->init(public_key);
|
||||
mExperiencesList->addItem(item, public_key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @file llpanelgroupexperiences.h
|
||||
* @brief List of experiences owned by a group.
|
||||
*
|
||||
* $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$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLPANELGROUPEXPERIENCES_H
|
||||
#define LL_LLPANELGROUPEXPERIENCES_H
|
||||
|
||||
#include "llpanelgroup.h"
|
||||
|
||||
class LLFlatListView;
|
||||
|
||||
class LLPanelGroupExperiences : public LLPanelGroupTab
|
||||
{
|
||||
public:
|
||||
LLPanelGroupExperiences();
|
||||
virtual ~LLPanelGroupExperiences();
|
||||
|
||||
// LLPanelGroupTab
|
||||
virtual void activate();
|
||||
|
||||
virtual BOOL postBuild();
|
||||
|
||||
virtual void setGroupID(const LLUUID& id);
|
||||
|
||||
void setExperienceList(const LLSD& experiences);
|
||||
|
||||
protected:
|
||||
LLFlatListView* mExperiencesList;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -86,19 +86,22 @@
|
|||
#include "llviewercontrol.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llfloatergotoline.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
#include "llexperienceassociationresponder.h"
|
||||
|
||||
const std::string HELLO_LSL =
|
||||
"default\n"
|
||||
"{\n"
|
||||
" state_entry()\n"
|
||||
" {\n"
|
||||
" llSay(0, \"Hello, Avatar!\");\n"
|
||||
" }\n"
|
||||
" state_entry()\n"
|
||||
" {\n"
|
||||
" llSay(0, \"Hello, Avatar!\");\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" touch_start(integer total_number)\n"
|
||||
" {\n"
|
||||
" llSay(0, \"Touched.\");\n"
|
||||
" }\n"
|
||||
" touch_start(integer total_number)\n"
|
||||
" {\n"
|
||||
" llSay(0, \"Touched.\");\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal";
|
||||
|
||||
|
|
@ -115,6 +118,26 @@ static bool have_script_upload_cap(LLUUID& object_id)
|
|||
return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty());
|
||||
}
|
||||
|
||||
|
||||
class ExperienceResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
ExperienceResponder(const LLHandle<LLLiveLSLEditor>& parent):mParent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
LLHandle<LLLiveLSLEditor> mParent;
|
||||
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
LLLiveLSLEditor* parent = mParent.get();
|
||||
if(!parent)
|
||||
return;
|
||||
|
||||
parent->setExperienceIds(getContent()["experience_ids"]);
|
||||
}
|
||||
};
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
/// LLLiveLSLFile
|
||||
/// ---------------------------------------------------------------------------
|
||||
|
|
@ -193,7 +216,7 @@ private:
|
|||
protected:
|
||||
LLLineEditor* mSearchBox;
|
||||
LLLineEditor* mReplaceBox;
|
||||
void onSearchBoxCommit();
|
||||
void onSearchBoxCommit();
|
||||
};
|
||||
|
||||
LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;
|
||||
|
|
@ -402,6 +425,55 @@ LLScriptEdCore::~LLScriptEdCore()
|
|||
}
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::experienceChanged()
|
||||
{
|
||||
if(mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID())
|
||||
{
|
||||
mScriptEd->enableSave(getIsModifiable());
|
||||
//getChildView("Save_btn")->setEnabled(TRUE);
|
||||
mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID());
|
||||
updateExperiencePanel();
|
||||
}
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::onViewProfile( LLUICtrl *ui, void* userdata )
|
||||
{
|
||||
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
|
||||
|
||||
LLUUID id;
|
||||
if(self->mExperienceEnabled->get())
|
||||
{
|
||||
id=self->mScriptEd->getAssociatedExperience();
|
||||
if(id.notNull())
|
||||
{
|
||||
LLFloaterReg::showInstance("experience_profile", id, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::onToggleExperience( LLUICtrl *ui, void* userdata )
|
||||
{
|
||||
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
|
||||
|
||||
LLUUID id;
|
||||
if(self->mExperienceEnabled->get())
|
||||
{
|
||||
if(self->mScriptEd->getAssociatedExperience().isNull())
|
||||
{
|
||||
id=self->mExperienceIds.beginArray()->asUUID();
|
||||
}
|
||||
}
|
||||
|
||||
if(id != self->mScriptEd->getAssociatedExperience())
|
||||
{
|
||||
self->mScriptEd->enableSave(self->getIsModifiable());
|
||||
}
|
||||
self->mScriptEd->setAssociatedExperience(id);
|
||||
|
||||
self->updateExperiencePanel();
|
||||
}
|
||||
|
||||
BOOL LLScriptEdCore::postBuild()
|
||||
{
|
||||
mErrorList = getChild<LLScrollListCtrl>("lsl errors");
|
||||
|
|
@ -828,7 +900,7 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS
|
|||
case 2: // "Cancel"
|
||||
default:
|
||||
// If we were quitting, we didn't really mean it.
|
||||
LLAppViewer::instance()->abortQuit();
|
||||
LLAppViewer::instance()->abortQuit();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -863,8 +935,8 @@ void LLScriptEdCore::onBtnDynamicHelp()
|
|||
LLKeywordToken *token;
|
||||
LLKeywords::keyword_iterator_t token_it;
|
||||
for (token_it = mEditor->keywordsBegin();
|
||||
token_it != mEditor->keywordsEnd();
|
||||
++token_it)
|
||||
token_it != mEditor->keywordsEnd();
|
||||
++token_it)
|
||||
{
|
||||
token = token_it->second;
|
||||
help_combo->add(wstring_to_utf8str(token->getToken()));
|
||||
|
|
@ -1216,6 +1288,141 @@ bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata)
|
|||
return (self && self->mEditor) ? self->mEditor->canLoadOrSaveToFile() : FALSE;
|
||||
}
|
||||
|
||||
LLUUID LLScriptEdCore::getAssociatedExperience()const
|
||||
{
|
||||
return mAssociatedExperience;
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids )
|
||||
{
|
||||
mExperienceIds=experience_ids;
|
||||
updateExperiencePanel();
|
||||
}
|
||||
|
||||
|
||||
void LLLiveLSLEditor::updateExperiencePanel()
|
||||
{
|
||||
if(mScriptEd->getAssociatedExperience().isNull())
|
||||
{
|
||||
mExperienceEnabled->set(FALSE);
|
||||
mExperiences->setVisible(FALSE);
|
||||
if(mExperienceIds.size()>0)
|
||||
{
|
||||
mExperienceEnabled->setEnabled(TRUE);
|
||||
mExperienceEnabled->setToolTip(getString("add_experiences"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mExperienceEnabled->setEnabled(FALSE);
|
||||
mExperienceEnabled->setToolTip(getString("no_experiences"));
|
||||
}
|
||||
getChild<LLButton>("view_profile")->setVisible(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mExperienceEnabled->setToolTip(getString("experience_enabled"));
|
||||
mExperienceEnabled->setEnabled(getIsModifiable());
|
||||
mExperiences->setVisible(TRUE);
|
||||
mExperienceEnabled->set(TRUE);
|
||||
getChild<LLButton>("view_profile")->setToolTip(getString("show_experience_profile"));
|
||||
buildExperienceList();
|
||||
}
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::buildExperienceList()
|
||||
{
|
||||
mExperiences->clearRows();
|
||||
bool foundAssociated=false;
|
||||
const LLUUID& associated = mScriptEd->getAssociatedExperience();
|
||||
LLUUID last;
|
||||
LLScrollListItem* item;
|
||||
for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it)
|
||||
{
|
||||
LLUUID id = it->asUUID();
|
||||
EAddPosition position = ADD_BOTTOM;
|
||||
if(id == associated)
|
||||
{
|
||||
foundAssociated = true;
|
||||
position = ADD_TOP;
|
||||
}
|
||||
|
||||
const LLSD& experience = LLExperienceCache::get(id);
|
||||
if(experience.isUndefined())
|
||||
{
|
||||
mExperiences->add(getString("loading"), id, position);
|
||||
last = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string experience_name_string = experience[LLExperienceCache::NAME].asString();
|
||||
if (experience_name_string.empty())
|
||||
{
|
||||
experience_name_string = LLTrans::getString("ExperienceNameUntitled");
|
||||
}
|
||||
mExperiences->add(experience_name_string, id, position);
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundAssociated )
|
||||
{
|
||||
const LLSD& experience = LLExperienceCache::get(associated);
|
||||
if(experience.isDefined())
|
||||
{
|
||||
std::string experience_name_string = experience[LLExperienceCache::NAME].asString();
|
||||
if (experience_name_string.empty())
|
||||
{
|
||||
experience_name_string = LLTrans::getString("ExperienceNameUntitled");
|
||||
}
|
||||
item=mExperiences->add(experience_name_string, associated, ADD_TOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
item=mExperiences->add(getString("loading"), associated, ADD_TOP);
|
||||
last = associated;
|
||||
}
|
||||
item->setEnabled(FALSE);
|
||||
}
|
||||
|
||||
if(last.notNull())
|
||||
{
|
||||
mExperiences->setEnabled(FALSE);
|
||||
LLExperienceCache::get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
mExperiences->setEnabled(TRUE);
|
||||
getChild<LLButton>("view_profile")->setVisible(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLScriptEdCore::setAssociatedExperience( const LLUUID& experience_id )
|
||||
{
|
||||
mAssociatedExperience = experience_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLLiveLSLEditor::requestExperiences()
|
||||
{
|
||||
if (!getIsModifiable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
std::string lookup_url=region->getCapability("GetCreatorExperiences");
|
||||
if(!lookup_url.empty())
|
||||
{
|
||||
LLHTTPClient::get(lookup_url, new ExperienceResponder(getDerivedHandle<LLLiveLSLEditor>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
/// LLScriptEdContainer
|
||||
/// ---------------------------------------------------------------------------
|
||||
|
|
@ -1234,7 +1441,7 @@ std::string LLScriptEdContainer::getTmpFileName()
|
|||
std::string script_id = mObjectUUID.asString() + "_" + mItemUUID.asString();
|
||||
|
||||
// Use MD5 sum to make the file name shorter and not exceed maximum path length.
|
||||
char script_id_hash_str[33]; /* Flawfinder: ignore */
|
||||
char script_id_hash_str[33]; /* Flawfinder: ignore */
|
||||
LLMD5 script_id_hash((const U8 *)script_id.c_str());
|
||||
script_id_hash.hex_digest(script_id_hash_str);
|
||||
|
||||
|
|
@ -1772,6 +1979,16 @@ BOOL LLLiveLSLEditor::postBuild()
|
|||
mScriptEd->mEditor->makePristine();
|
||||
mScriptEd->mEditor->setFocus(TRUE);
|
||||
|
||||
|
||||
mExperiences = getChild<LLComboBox>("Experiences...");
|
||||
mExperiences->setCommitCallback(boost::bind(&LLLiveLSLEditor::experienceChanged, this));
|
||||
|
||||
mExperienceEnabled = getChild<LLCheckBoxCtrl>("enable_xp");
|
||||
|
||||
childSetCommitCallback("enable_xp", onToggleExperience, this);
|
||||
childSetCommitCallback("view_profile", onViewProfile, this);
|
||||
|
||||
|
||||
return LLPreview::postBuild();
|
||||
}
|
||||
|
||||
|
|
@ -1815,61 +2032,60 @@ void LLLiveLSLEditor::loadAsset()
|
|||
if(object)
|
||||
{
|
||||
LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(object->getInventoryObject(mItemUUID));
|
||||
if(item
|
||||
&& (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE)
|
||||
|| gAgent.isGodlike()))
|
||||
{
|
||||
mItem = new LLViewerInventoryItem(item);
|
||||
//LL_INFOS() << "asset id " << mItem->getAssetUUID() << LL_ENDL;
|
||||
}
|
||||
|
||||
if(!gAgent.isGodlike()
|
||||
&& (item
|
||||
&& (!gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE)
|
||||
|| !gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE))))
|
||||
if(item)
|
||||
{
|
||||
mItem = new LLViewerInventoryItem(item);
|
||||
mScriptEd->setScriptText(getString("not_allowed"), FALSE);
|
||||
mScriptEd->mEditor->makePristine();
|
||||
mScriptEd->enableSave(FALSE);
|
||||
mAssetStatus = PREVIEW_ASSET_LOADED;
|
||||
}
|
||||
else if(item && mItem.notNull())
|
||||
{
|
||||
// request the text from the object
|
||||
ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
|
||||
|
||||
bool isGodlike = gAgent.isGodlike();
|
||||
bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
|
||||
mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE);
|
||||
|
||||
if(!isGodlike && (!copyManipulate || !mIsModifiable))
|
||||
{
|
||||
mItem = new LLViewerInventoryItem(item);
|
||||
mScriptEd->setScriptText(getString("not_allowed"), FALSE);
|
||||
mScriptEd->mEditor->makePristine();
|
||||
mScriptEd->enableSave(FALSE);
|
||||
mAssetStatus = PREVIEW_ASSET_LOADED;
|
||||
}
|
||||
else if(copyManipulate || isGodlike)
|
||||
{
|
||||
mItem = new LLViewerInventoryItem(item);
|
||||
// request the text from the object
|
||||
LLSD* user_data = new LLSD();
|
||||
user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID);
|
||||
gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
item->getPermissions().getOwner(),
|
||||
object->getID(),
|
||||
item->getUUID(),
|
||||
item->getAssetUUID(),
|
||||
item->getType(),
|
||||
&LLLiveLSLEditor::onLoadComplete,
|
||||
(void*)user_data,
|
||||
TRUE);
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_GetScriptRunning);
|
||||
msg->nextBlockFast(_PREHASH_Script);
|
||||
msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID);
|
||||
msg->addUUIDFast(_PREHASH_ItemID, mItemUUID);
|
||||
msg->sendReliable(object->getRegion()->getHost());
|
||||
mAskedForRunningInfo = TRUE;
|
||||
mAssetStatus = PREVIEW_ASSET_LOADING;
|
||||
gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
item->getPermissions().getOwner(),
|
||||
object->getID(),
|
||||
item->getUUID(),
|
||||
item->getAssetUUID(),
|
||||
item->getType(),
|
||||
&LLLiveLSLEditor::onLoadComplete,
|
||||
(void*)user_data,
|
||||
TRUE);
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_GetScriptRunning);
|
||||
msg->nextBlockFast(_PREHASH_Script);
|
||||
msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID);
|
||||
msg->addUUIDFast(_PREHASH_ItemID, mItemUUID);
|
||||
msg->sendReliable(object->getRegion()->getHost());
|
||||
mAskedForRunningInfo = TRUE;
|
||||
mAssetStatus = PREVIEW_ASSET_LOADING;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if(mItem.isNull())
|
||||
{
|
||||
mScriptEd->setScriptText(LLStringUtil::null, FALSE);
|
||||
mScriptEd->mEditor->makePristine();
|
||||
mAssetStatus = PREVIEW_ASSET_LOADED;
|
||||
mIsModifiable = FALSE;
|
||||
}
|
||||
|
||||
mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY,
|
||||
item->getPermissions(),
|
||||
GP_OBJECT_MANIPULATE);
|
||||
|
||||
refreshFromItem();
|
||||
// This is commented out, because we don't completely
|
||||
// handle script exports yet.
|
||||
/*
|
||||
|
|
@ -1906,6 +2122,8 @@ void LLLiveLSLEditor::loadAsset()
|
|||
time_corrected());
|
||||
mAssetStatus = PREVIEW_ASSET_LOADED;
|
||||
}
|
||||
|
||||
requestExperiences();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -2169,7 +2387,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
|
|||
BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
|
||||
if (!url.empty())
|
||||
{
|
||||
uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running);
|
||||
uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running, mScriptEd->getAssociatedExperience());
|
||||
}
|
||||
else if (gAssetStorage)
|
||||
{
|
||||
|
|
@ -2181,7 +2399,8 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
|
|||
const std::string& filename,
|
||||
const LLUUID& task_id,
|
||||
const LLUUID& item_id,
|
||||
BOOL is_running)
|
||||
BOOL is_running,
|
||||
const LLUUID& experience_public_id )
|
||||
{
|
||||
LL_INFOS() << "Update Task Inventory via capability " << url << LL_ENDL;
|
||||
LLSD body;
|
||||
|
|
@ -2189,6 +2408,7 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
|
|||
body["item_id"] = item_id;
|
||||
body["is_script_running"] = is_running;
|
||||
body["target"] = monoChecked() ? "mono" : "lsl2";
|
||||
body["experience"] = experience_public_id;
|
||||
LLHTTPClient::post(url, body,
|
||||
new LLUpdateTaskInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT));
|
||||
}
|
||||
|
|
@ -2449,3 +2669,18 @@ BOOL LLLiveLSLEditor::monoChecked() const
|
|||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::setAssociatedExperience( LLHandle<LLLiveLSLEditor> editor, const LLSD& experience )
|
||||
{
|
||||
LLLiveLSLEditor* scriptEd = editor.get();
|
||||
if(scriptEd)
|
||||
{
|
||||
LLUUID id;
|
||||
if(experience.has(LLExperienceCache::EXPERIENCE_ID))
|
||||
{
|
||||
id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
}
|
||||
scriptEd->mScriptEd->setAssociatedExperience(id);
|
||||
scriptEd->updateExperiencePanel();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class LLVFS;
|
|||
class LLViewerInventoryItem;
|
||||
class LLScriptEdContainer;
|
||||
class LLFloaterGotoLine;
|
||||
class LLFloaterExperienceProfile;
|
||||
|
||||
// Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these.
|
||||
class LLScriptEdCore : public LLPanel
|
||||
|
|
@ -107,12 +108,14 @@ public:
|
|||
static void onBtnInsertSample(void*);
|
||||
static void onBtnInsertFunction(LLUICtrl*, void*);
|
||||
static void onBtnLoadFromFile(void*);
|
||||
static void onBtnSaveToFile(void*);
|
||||
static void onBtnSaveToFile(void*);
|
||||
|
||||
static bool enableSaveToFileMenu(void* userdata);
|
||||
static bool enableLoadFromFileMenu(void* userdata);
|
||||
|
||||
virtual bool hasAccelerators() const { return true; }
|
||||
virtual bool hasAccelerators() const { return true; }
|
||||
LLUUID getAssociatedExperience()const;
|
||||
void setAssociatedExperience( const LLUUID& experience_id );
|
||||
|
||||
void setScriptName(const std::string& name){mScriptName = name;};
|
||||
|
||||
|
|
@ -146,8 +149,8 @@ private:
|
|||
void (*mLoadCallback)(void* userdata);
|
||||
void (*mSaveCallback)(void* userdata, BOOL close_after_save);
|
||||
void (*mSearchReplaceCallback) (void* userdata);
|
||||
void* mUserdata;
|
||||
LLComboBox *mFunctions;
|
||||
void* mUserdata;
|
||||
LLComboBox *mFunctions;
|
||||
BOOL mForceClose;
|
||||
LLPanel* mCodePanel;
|
||||
LLScrollListCtrl* mErrorList;
|
||||
|
|
@ -159,6 +162,7 @@ private:
|
|||
BOOL mEnableSave;
|
||||
BOOL mHasScriptData;
|
||||
LLLiveLSLFile* mLiveFile;
|
||||
LLUUID mAssociatedExperience;
|
||||
|
||||
LLScriptEdContainer* mContainer; // parent view
|
||||
|
||||
|
|
@ -245,7 +249,18 @@ public:
|
|||
|
||||
/*virtual*/ BOOL postBuild();
|
||||
|
||||
void setIsNew() { mIsNew = TRUE; }
|
||||
void setIsNew() { mIsNew = TRUE; }
|
||||
|
||||
static void setAssociatedExperience( LLHandle<LLLiveLSLEditor> editor, const LLSD& experience );
|
||||
static void onToggleExperience(LLUICtrl *ui, void* userdata);
|
||||
static void onViewProfile(LLUICtrl *ui, void* userdata);
|
||||
|
||||
void setExperienceIds(const LLSD& experience_ids);
|
||||
void buildExperienceList();
|
||||
void updateExperiencePanel();
|
||||
void requestExperiences();
|
||||
void experienceChanged();
|
||||
void addAssociatedExperience(const LLSD& experience);
|
||||
|
||||
private:
|
||||
virtual BOOL canClose();
|
||||
|
|
@ -256,10 +271,11 @@ private:
|
|||
void loadAsset(BOOL is_new);
|
||||
/*virtual*/ void saveIfNeeded(bool sync = true);
|
||||
void uploadAssetViaCaps(const std::string& url,
|
||||
const std::string& filename,
|
||||
const std::string& filename,
|
||||
const LLUUID& task_id,
|
||||
const LLUUID& item_id,
|
||||
BOOL is_running);
|
||||
BOOL is_running,
|
||||
const LLUUID& experience_public_id);
|
||||
void uploadAssetLegacy(const std::string& filename,
|
||||
LLViewerObject* object,
|
||||
const LLTransactionID& tid,
|
||||
|
|
@ -300,9 +316,16 @@ private:
|
|||
S32 mPendingUploads;
|
||||
|
||||
BOOL getIsModifiable() const { return mIsModifiable; } // Evaluated on load assert
|
||||
|
||||
|
||||
LLCheckBoxCtrl* mMonoCheckbox;
|
||||
BOOL mIsModifiable;
|
||||
|
||||
|
||||
LLComboBox* mExperiences;
|
||||
LLCheckBoxCtrl* mExperienceEnabled;
|
||||
LLSD mExperienceIds;
|
||||
|
||||
LLHandle<LLFloater> mExperienceProfile;
|
||||
};
|
||||
|
||||
#endif // LL_LLPREVIEWSCRIPT_H
|
||||
|
|
|
|||
|
|
@ -541,19 +541,23 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
|
|||
{
|
||||
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
|
||||
|
||||
LLPanel* panel_to_delete = panel;
|
||||
|
||||
if( it != mToastList.end() && panel)
|
||||
{
|
||||
LLToast* toast = it->getToast();
|
||||
if (toast)
|
||||
{
|
||||
LLPanel* old_panel = toast->getPanel();
|
||||
toast->removeChild(old_panel);
|
||||
delete old_panel;
|
||||
toast->insertPanel(panel);
|
||||
toast->startTimer();
|
||||
LLPanel* old_panel = toast->getPanel();
|
||||
toast->removeChild(old_panel);
|
||||
panel_to_delete = old_panel;
|
||||
toast->insertPanel(panel);
|
||||
toast->startTimer();
|
||||
}
|
||||
redrawToasts();
|
||||
}
|
||||
|
||||
delete panel_to_delete;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@
|
|||
#include "llviewercontrol.h"
|
||||
#include "llviewerinventory.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llexperienceassociationresponder.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -319,6 +322,15 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
|
|||
is_obj_modify = object->permOwnerModify();
|
||||
}
|
||||
|
||||
if(item->getInventoryType() == LLInventoryType::IT_LSL)
|
||||
{
|
||||
getChildView("LabelItemExperienceTitle")->setVisible(TRUE);
|
||||
LLTextBox* tb = getChild<LLTextBox>("LabelItemExperience");
|
||||
tb->setText(getString("loading_experience"));
|
||||
tb->setVisible(TRUE);
|
||||
ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle<LLSidepanelItemInfo>(), _1));
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
// ITEM NAME & DESC //
|
||||
//////////////////////
|
||||
|
|
@ -674,6 +686,29 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLSidepanelItemInfo::setAssociatedExperience( LLHandle<LLSidepanelItemInfo> hInfo, const LLSD& experience )
|
||||
{
|
||||
LLSidepanelItemInfo* info = hInfo.get();
|
||||
if(info)
|
||||
{
|
||||
LLUUID id;
|
||||
if(experience.has(LLExperienceCache::EXPERIENCE_ID))
|
||||
{
|
||||
id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
}
|
||||
if(id.notNull())
|
||||
{
|
||||
info->getChild<LLTextBox>("LabelItemExperience")->setText(LLSLURL("experience", id, "profile").getSLURLString());
|
||||
}
|
||||
else
|
||||
{
|
||||
info->getChild<LLTextBox>("LabelItemExperience")->setText(LLTrans::getString("ExperienceNameNull"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLSidepanelItemInfo::startObjectInventoryObserver()
|
||||
{
|
||||
if (!mObjectInventoryObserver)
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ protected:
|
|||
void refreshFromItem(LLViewerInventoryItem* item);
|
||||
|
||||
private:
|
||||
static void setAssociatedExperience( LLHandle<LLSidepanelItemInfo> hInfo, const LLSD& experience );
|
||||
|
||||
void startObjectInventoryObserver();
|
||||
void stopObjectInventoryObserver();
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#include "llares.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "lllandmark.h"
|
||||
#include "llcachename.h"
|
||||
#include "lldir.h"
|
||||
|
|
@ -194,6 +195,7 @@
|
|||
#include "llevents.h"
|
||||
#include "llstartuplistener.h"
|
||||
#include "lltoolbarview.h"
|
||||
#include "llexperiencelog.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "lldxhardware.h"
|
||||
|
|
@ -1305,6 +1307,9 @@ bool idle_startup()
|
|||
// object is created. I think this must be done after setting the region. JC
|
||||
gAgent.setPositionAgent(agent_start_position_region);
|
||||
|
||||
display_startup();
|
||||
LLStartUp::initExperiences();
|
||||
|
||||
display_startup();
|
||||
LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT );
|
||||
|
||||
|
|
@ -2824,6 +2829,14 @@ void LLStartUp::initNameCache()
|
|||
LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames"));
|
||||
}
|
||||
|
||||
|
||||
void LLStartUp::initExperiences()
|
||||
{
|
||||
LLAppViewer::instance()->loadExperienceCache();
|
||||
LLExperienceCache::initClass();
|
||||
LLExperienceLog::instance().initialize();
|
||||
}
|
||||
|
||||
void LLStartUp::cleanupNameCache()
|
||||
{
|
||||
LLAvatarNameCache::cleanupClass();
|
||||
|
|
@ -3525,3 +3538,4 @@ void transition_back_to_login_panel(const std::string& emsg)
|
|||
reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
|
||||
gSavedSettings.setBOOL("AutoLogin", FALSE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public:
|
|||
static void fontInit();
|
||||
|
||||
static void initNameCache();
|
||||
static void initExperiences();
|
||||
|
||||
static void cleanupNameCache();
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
const S32 BOTTOM_PAD = VPAD * 3;
|
||||
const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding
|
||||
S32 BUTTON_WIDTH = 90;
|
||||
// *TODO: magic numbers(?) - copied from llnotify.cpp(250)
|
||||
// *TODO: magic numbers - copied from llnotify.cpp(250)
|
||||
const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@
|
|||
#include "llfloatereditsky.h"
|
||||
#include "llfloatereditwater.h"
|
||||
#include "llfloaterenvironmentsettings.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
#include "llfloaterexperiences.h"
|
||||
#include "llfloaterexperiencepicker.h"
|
||||
#include "llfloaterevent.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
|
|
@ -213,8 +216,11 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("env_edit_water", "floater_edit_water_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditWater>);
|
||||
LLFloaterReg::add("env_edit_day_cycle", "floater_edit_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditDayCycle>);
|
||||
|
||||
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
|
||||
|
||||
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
|
||||
LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
|
||||
LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperienceProfile>);
|
||||
LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
|
||||
|
||||
LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
|
||||
|
||||
LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@
|
|||
#include <boost/regex.hpp>
|
||||
|
||||
#include "llnotificationmanager.h" //
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
#if LL_MSVC
|
||||
// disable boost::lexical_cast warning
|
||||
|
|
@ -142,6 +143,7 @@ extern bool gShiftFrame;
|
|||
bool check_offer_throttle(const std::string& from_name, bool check_only);
|
||||
bool check_asset_previewable(const LLAssetType::EType asset_type);
|
||||
static void process_money_balance_reply_extended(LLMessageSystem* msg);
|
||||
bool handle_trusted_experiences_notification(const LLSD&);
|
||||
|
||||
//inventory offer throttle globals
|
||||
LLFrameTimer gThrottleTimer;
|
||||
|
|
@ -5694,108 +5696,33 @@ bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD&
|
|||
// some of the server notifications need special handling. This is where we do that.
|
||||
bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
|
||||
{
|
||||
U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
|
||||
std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
|
||||
LLStringUtil::toLower(regionMaturity);
|
||||
llsdBlock["REGIONMATURITY"] = regionMaturity;
|
||||
bool returnValue = false;
|
||||
LLNotificationPtr maturityLevelNotification;
|
||||
std::string notifySuffix = "_Notify";
|
||||
if (regionAccess == SIM_ACCESS_MATURE)
|
||||
if(llsdBlock.has("_region_access"))
|
||||
{
|
||||
if (gAgent.isTeen())
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
returnValue = true;
|
||||
|
||||
notifySuffix = "_NotifyAdultsOnly";
|
||||
}
|
||||
else if (gAgent.prefersPG())
|
||||
{
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
|
||||
{
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
else if (regionAccess == SIM_ACCESS_ADULT)
|
||||
{
|
||||
if (!gAgent.isAdult())
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
returnValue = true;
|
||||
|
||||
notifySuffix = "_NotifyAdultsOnly";
|
||||
}
|
||||
else if (gAgent.prefersPG() || gAgent.prefersMature())
|
||||
{
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
|
||||
{
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored())
|
||||
{
|
||||
// Given a simple notification if no maturityLevelNotification is set or it is ignore
|
||||
LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// some of the server notifications need special handling. This is where we do that.
|
||||
bool handle_teleport_access_blocked(LLSD& llsdBlock, const std::string & notificationID, const std::string & defaultMessage)
|
||||
{
|
||||
U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
|
||||
std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
|
||||
LLStringUtil::toLower(regionMaturity);
|
||||
llsdBlock["REGIONMATURITY"] = regionMaturity;
|
||||
|
||||
bool returnValue = false;
|
||||
LLNotificationPtr tp_failure_notification;
|
||||
std::string notifySuffix;
|
||||
|
||||
if (notificationID == std::string("TeleportEntryAccessBlocked"))
|
||||
{
|
||||
notifySuffix = "_Notify";
|
||||
U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
|
||||
std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
|
||||
LLStringUtil::toLower(regionMaturity);
|
||||
llsdBlock["REGIONMATURITY"] = regionMaturity;
|
||||
LLNotificationPtr maturityLevelNotification;
|
||||
std::string notifySuffix = "_Notify";
|
||||
if (regionAccess == SIM_ACCESS_MATURE)
|
||||
{
|
||||
if (gAgent.isTeen())
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
returnValue = true;
|
||||
|
||||
notifySuffix = "_NotifyAdultsOnly";
|
||||
}
|
||||
else if (gAgent.prefersPG())
|
||||
{
|
||||
if (gAgent.hasRestartableFailedTeleportRequest())
|
||||
{
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else
|
||||
else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -5804,54 +5731,157 @@ bool handle_teleport_access_blocked(LLSD& llsdBlock, const std::string & notific
|
|||
if (!gAgent.isAdult())
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
returnValue = true;
|
||||
|
||||
notifySuffix = "_NotifyAdultsOnly";
|
||||
}
|
||||
else if (gAgent.prefersPG() || gAgent.prefersMature())
|
||||
{
|
||||
if (gAgent.hasRestartableFailedTeleportRequest())
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
|
||||
{
|
||||
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored())
|
||||
{
|
||||
// Given a simple notification if no maturityLevelNotification is set or it is ignore
|
||||
LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
bool handle_trusted_experiences_notification(const LLSD& llsdBlock)
|
||||
{
|
||||
if(llsdBlock.has("trusted_experiences"))
|
||||
{
|
||||
std::ostringstream str;
|
||||
const LLSD& experiences = llsdBlock["trusted_experiences"];
|
||||
LLSD::array_const_iterator it = experiences.beginArray();
|
||||
for(/**/; it != experiences.endArray(); ++it)
|
||||
{
|
||||
str<<LLSLURL("experience", it->asUUID(), "profile").getSLURLString() << "\n";
|
||||
}
|
||||
std::string str_list = str.str();
|
||||
if(!str_list.empty())
|
||||
{
|
||||
LLNotificationsUtil::add("TrustedExperiencesAvailable", LLSD::emptyMap().with("EXPERIENCE_LIST", (LLSD)str_list));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// some of the server notifications need special handling. This is where we do that.
|
||||
bool handle_teleport_access_blocked(LLSD& llsdBlock, const std::string & notificationID, const std::string & defaultMessage)
|
||||
{
|
||||
bool returnValue = false;
|
||||
if(llsdBlock.has("_region_access"))
|
||||
{
|
||||
U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
|
||||
std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
|
||||
LLStringUtil::toLower(regionMaturity);
|
||||
llsdBlock["REGIONMATURITY"] = regionMaturity;
|
||||
|
||||
LLNotificationPtr tp_failure_notification;
|
||||
std::string notifySuffix;
|
||||
|
||||
if (notificationID == std::string("TeleportEntryAccessBlocked"))
|
||||
{
|
||||
notifySuffix = "_Notify";
|
||||
if (regionAccess == SIM_ACCESS_MATURE)
|
||||
{
|
||||
if (gAgent.isTeen())
|
||||
{
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
returnValue = true;
|
||||
|
||||
notifySuffix = "_NotifyAdultsOnly";
|
||||
}
|
||||
else if (gAgent.prefersPG())
|
||||
{
|
||||
if (gAgent.hasRestartableFailedTeleportRequest())
|
||||
{
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
else if (regionAccess == SIM_ACCESS_ADULT)
|
||||
{
|
||||
if (!gAgent.isAdult())
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
|
||||
returnValue = true;
|
||||
|
||||
notifySuffix = "_NotifyAdultsOnly";
|
||||
}
|
||||
else if (gAgent.prefersPG() || gAgent.prefersMature())
|
||||
{
|
||||
if (gAgent.hasRestartableFailedTeleportRequest())
|
||||
{
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
} // End of special handling for "TeleportEntryAccessBlocked"
|
||||
else
|
||||
{ // Normal case, no message munging
|
||||
gAgent.clearTeleportRequest();
|
||||
if (LLNotifications::getInstance()->templateExists(notificationID))
|
||||
{
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID, llsdBlock, llsdBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.clearTeleportRequest();
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
|
||||
returnValue = true;
|
||||
llsdBlock["MESSAGE"] = defaultMessage;
|
||||
tp_failure_notification = LLNotificationsUtil::add("GenericAlertOK", llsdBlock);
|
||||
}
|
||||
}
|
||||
} // End of special handling for "TeleportEntryAccessBlocked"
|
||||
else
|
||||
{ // Normal case, no message munging
|
||||
gAgent.clearTeleportRequest();
|
||||
if (LLNotifications::getInstance()->templateExists(notificationID))
|
||||
{
|
||||
tp_failure_notification = LLNotificationsUtil::add(notificationID, llsdBlock, llsdBlock);
|
||||
returnValue = true;
|
||||
}
|
||||
else
|
||||
|
||||
if ((tp_failure_notification == NULL) || tp_failure_notification->isIgnored())
|
||||
{
|
||||
llsdBlock["MESSAGE"] = defaultMessage;
|
||||
tp_failure_notification = LLNotificationsUtil::add("GenericAlertOK", llsdBlock);
|
||||
// Given a simple notification if no tp_failure_notification is set or it is ignore
|
||||
LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
|
||||
}
|
||||
returnValue = true;
|
||||
}
|
||||
|
||||
if ((tp_failure_notification == NULL) || tp_failure_notification->isIgnored())
|
||||
{
|
||||
// Given a simple notification if no tp_failure_notification is set or it is ignore
|
||||
LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
|
||||
}
|
||||
|
||||
handle_trusted_experiences_notification(llsdBlock);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
|
@ -5881,6 +5911,9 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
handle_trusted_experiences_notification(llsdBlock);
|
||||
|
||||
if (
|
||||
(notificationID == "RegionEntryAccessBlocked") ||
|
||||
(notificationID == "LandClaimAccessBlocked") ||
|
||||
|
|
@ -6064,8 +6097,8 @@ void process_alert_core(const std::string& message, BOOL modal)
|
|||
std::string alert_name(message.substr(ALERT_PREFIX.length()));
|
||||
if (!handle_special_alerts(alert_name))
|
||||
{
|
||||
LLNotificationsUtil::add(alert_name);
|
||||
}
|
||||
LLNotificationsUtil::add(alert_name);
|
||||
}
|
||||
}
|
||||
else if (message.find(NOTIFY_PREFIX) == 0)
|
||||
{
|
||||
|
|
@ -6087,10 +6120,10 @@ void process_alert_core(const std::string& message, BOOL modal)
|
|||
LLFloaterRegionRestarting::close();
|
||||
}
|
||||
|
||||
std::string new_msg =LLNotifications::instance().getGlobalString(text);
|
||||
args["MESSAGE"] = new_msg;
|
||||
LLNotificationsUtil::add("SystemMessage", args);
|
||||
}
|
||||
std::string new_msg =LLNotifications::instance().getGlobalString(text);
|
||||
args["MESSAGE"] = new_msg;
|
||||
LLNotificationsUtil::add("SystemMessage", args);
|
||||
}
|
||||
else if (modal)
|
||||
{
|
||||
LLSD args;
|
||||
|
|
@ -6345,6 +6378,12 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
|
|||
return false;
|
||||
}
|
||||
|
||||
LLUUID experience;
|
||||
if(notification["payload"].has("experience"))
|
||||
{
|
||||
experience = notification["payload"]["experience"].asUUID();
|
||||
}
|
||||
|
||||
// check whether permissions were granted or denied
|
||||
BOOL allowed = TRUE;
|
||||
// the "yes/accept" button is the first button in the template, making it button 0
|
||||
|
|
@ -6354,6 +6393,16 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
|
|||
new_questions = 0;
|
||||
allowed = FALSE;
|
||||
}
|
||||
else if(experience.notNull())
|
||||
{
|
||||
LLSD permission;
|
||||
LLSD data;
|
||||
permission["permission"]="Allow";
|
||||
|
||||
data[experience.asString()]=permission;
|
||||
data["experience"]=experience;
|
||||
LLEventPumps::instance().obtain("experience_permission").post(data);
|
||||
}
|
||||
|
||||
LLUUID task_id = notification["payload"]["task_id"].asUUID();
|
||||
LLUUID item_id = notification["payload"]["item_id"].asUUID();
|
||||
|
|
@ -6380,7 +6429,27 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
|
|||
{
|
||||
script_question_mute(task_id,notification["payload"]["object_name"].asString());
|
||||
}
|
||||
if ( response["BlockExperience"] )
|
||||
{
|
||||
if(experience.notNull())
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region)
|
||||
return false;
|
||||
|
||||
std::string lookup_url=region->getCapability("ExperiencePreferences");
|
||||
if(lookup_url.empty())
|
||||
return false;
|
||||
LLSD permission;
|
||||
LLSD data;
|
||||
permission["permission"]="Block";
|
||||
|
||||
data[experience.asString()]=permission;
|
||||
LLHTTPClient::put(lookup_url, data, NULL);
|
||||
data["experience"]=experience;
|
||||
LLEventPumps::instance().obtain("experience_permission").post(data);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -6413,8 +6482,24 @@ void script_question_mute(const LLUUID& task_id, const std::string& object_name)
|
|||
|
||||
static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb);
|
||||
static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestionCaution", script_question_cb);
|
||||
static LLNotificationFunctorRegistration script_question_cb_reg_3("ScriptQuestionExperience", script_question_cb);
|
||||
static LLNotificationFunctorRegistration unknown_script_question_cb_reg("UnknownScriptQuestion", unknown_script_question_cb);
|
||||
|
||||
void process_script_experience_details(const LLSD& experience_details, LLSD args, LLSD payload)
|
||||
{
|
||||
if(experience_details[LLExperienceCache::PROPERTIES].asInteger() & LLExperienceCache::PROPERTY_GRID)
|
||||
{
|
||||
args["GRID_WIDE"] = LLTrans::getString("Grid-Scope");
|
||||
}
|
||||
else
|
||||
{
|
||||
args["GRID_WIDE"] = LLTrans::getString("Land-Scope");
|
||||
}
|
||||
args["EXPERIENCE"] = LLSLURL("experience", experience_details[LLExperienceCache::EXPERIENCE_ID].asUUID(), "profile").getSLURLString();
|
||||
|
||||
LLNotificationsUtil::add("ScriptQuestionExperience", args, payload);
|
||||
}
|
||||
|
||||
void process_script_question(LLMessageSystem *msg, void **user_data)
|
||||
{
|
||||
// *TODO: Translate owner name -> [FIRST] [LAST]
|
||||
|
|
@ -6426,6 +6511,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
|
|||
S32 questions;
|
||||
std::string object_name;
|
||||
std::string owner_name;
|
||||
LLUUID experienceid;
|
||||
|
||||
// taskid -> object key of object requesting permissions
|
||||
msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid );
|
||||
|
|
@ -6435,6 +6521,11 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
|
|||
msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectOwner, owner_name);
|
||||
msg->getS32Fast(_PREHASH_Data, _PREHASH_Questions, questions );
|
||||
|
||||
if(msg->has(_PREHASH_Experience))
|
||||
{
|
||||
msg->getUUIDFast(_PREHASH_Experience, _PREHASH_ExperienceID, experienceid);
|
||||
}
|
||||
|
||||
// Special case. If the objects are owned by this agent, throttle per-object instead
|
||||
// of per-owner. It's common for residents to reset a ton of scripts that re-request
|
||||
// permissions, as with tier boxes. UUIDs can't be valid agent names and vice-versa,
|
||||
|
|
@ -6521,20 +6612,21 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
|
|||
payload["owner_name"] = owner_name;
|
||||
|
||||
// check whether cautions are even enabled or not
|
||||
if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
|
||||
const char* notification = "ScriptQuestion";
|
||||
|
||||
if(caution && gSavedSettings.getBOOL("PermissionsCautionEnabled"))
|
||||
{
|
||||
if (caution)
|
||||
{
|
||||
args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : "";
|
||||
}
|
||||
// display the caution permissions prompt
|
||||
LLNotificationsUtil::add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload);
|
||||
args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : "";
|
||||
notification = "ScriptQuestionCaution";
|
||||
}
|
||||
else
|
||||
else if(experienceid.notNull())
|
||||
{
|
||||
// fall back to default behavior if cautions are entirely disabled
|
||||
LLNotificationsUtil::add("ScriptQuestion", args, payload);
|
||||
payload["experience"]=experienceid;
|
||||
LLExperienceCache::get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));
|
||||
return;
|
||||
}
|
||||
|
||||
LLNotificationsUtil::add(notification, args, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,8 +206,8 @@ void LLViewerParcelMgr::dump()
|
|||
mCurrentParcel->dump();
|
||||
LL_INFOS() << "banning " << mCurrentParcel->mBanList.size() << LL_ENDL;
|
||||
|
||||
access_map_const_iterator cit = mCurrentParcel->mBanList.begin();
|
||||
access_map_const_iterator end = mCurrentParcel->mBanList.end();
|
||||
LLAccessEntry::map::const_iterator cit = mCurrentParcel->mBanList.begin();
|
||||
LLAccessEntry::map::const_iterator end = mCurrentParcel->mBanList.end();
|
||||
for ( ; cit != end; ++cit)
|
||||
{
|
||||
LL_INFOS() << "ban id " << (*cit).first << LL_ENDL;
|
||||
|
|
@ -893,7 +893,7 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
|
|||
if (!region) return;
|
||||
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
||||
|
||||
|
||||
if (flags & AL_BAN)
|
||||
{
|
||||
|
|
@ -903,6 +903,14 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
|
|||
{
|
||||
mCurrentParcel->mAccessList.clear();
|
||||
}
|
||||
if (flags & AL_ALLOW_EXPERIENCE)
|
||||
{
|
||||
mCurrentParcel->clearExperienceKeysByType(EXPERIENCE_KEY_TYPE_ALLOWED);
|
||||
}
|
||||
if (flags & AL_BLOCK_EXPERIENCE)
|
||||
{
|
||||
mCurrentParcel->clearExperienceKeysByType(EXPERIENCE_KEY_TYPE_BLOCKED);
|
||||
}
|
||||
|
||||
// Only the headers differ
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListRequest);
|
||||
|
|
@ -1671,7 +1679,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
|
|||
}
|
||||
|
||||
// Request access list information for this land
|
||||
parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN);
|
||||
parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN | AL_ALLOW_EXPERIENCE | AL_BLOCK_EXPERIENCE);
|
||||
|
||||
// Request dwell for this land, if it's not public land.
|
||||
parcel_mgr.mSelectedDwell = DWELL_NAN;
|
||||
|
|
@ -1836,6 +1844,14 @@ void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void
|
|||
{
|
||||
parcel->unpackAccessEntries(msg, &(parcel->mBanList) );
|
||||
}
|
||||
else if (message_flags & AL_ALLOW_EXPERIENCE)
|
||||
{
|
||||
parcel->unpackExperienceEntries(msg, EXPERIENCE_KEY_TYPE_ALLOWED);
|
||||
}
|
||||
else if (message_flags & AL_BLOCK_EXPERIENCE)
|
||||
{
|
||||
parcel->unpackExperienceEntries(msg, EXPERIENCE_KEY_TYPE_BLOCKED);
|
||||
}
|
||||
/*else if (message_flags & AL_RENTER)
|
||||
{
|
||||
parcel->unpackAccessEntries(msg, &(parcel->mRenterList) );
|
||||
|
|
@ -1870,10 +1886,6 @@ void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**)
|
|||
|
||||
void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
|
||||
{
|
||||
|
||||
LLUUID transactionUUID;
|
||||
transactionUUID.generate();
|
||||
|
||||
if (!mSelected)
|
||||
{
|
||||
return;
|
||||
|
|
@ -1882,125 +1894,92 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
|
|||
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
|
||||
if (!region) return;
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
LLParcel* parcel = mCurrentParcel;
|
||||
if (!parcel) return;
|
||||
|
||||
if (which & AL_ACCESS)
|
||||
{
|
||||
S32 count = parcel->mAccessList.size();
|
||||
S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
|
||||
S32 sequence_id = 1;
|
||||
BOOL start_message = TRUE;
|
||||
BOOL initial = TRUE;
|
||||
|
||||
access_map_const_iterator cit = parcel->mAccessList.begin();
|
||||
access_map_const_iterator end = parcel->mAccessList.end();
|
||||
while ( (cit != end) || initial )
|
||||
{
|
||||
if (start_message)
|
||||
{
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
|
||||
msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
|
||||
msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
|
||||
msg->addS32Fast(_PREHASH_Sections, num_sections);
|
||||
start_message = FALSE;
|
||||
|
||||
if (initial && (cit == end))
|
||||
{
|
||||
// pack an empty block if there will be no data
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
|
||||
msg->addS32Fast(_PREHASH_Time, 0 );
|
||||
msg->addU32Fast(_PREHASH_Flags, 0 );
|
||||
}
|
||||
|
||||
initial = FALSE;
|
||||
sequence_id++;
|
||||
|
||||
}
|
||||
|
||||
while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
|
||||
{
|
||||
|
||||
const LLAccessEntry& entry = (*cit).second;
|
||||
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, entry.mID );
|
||||
msg->addS32Fast(_PREHASH_Time, entry.mTime );
|
||||
msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
|
||||
++cit;
|
||||
}
|
||||
|
||||
start_message = TRUE;
|
||||
msg->sendReliable( region->getHost() );
|
||||
}
|
||||
sendParcelAccessListUpdate(AL_ACCESS, parcel->mAccessList, region, parcel->getLocalID());
|
||||
}
|
||||
|
||||
if (which & AL_BAN)
|
||||
{
|
||||
S32 count = parcel->mBanList.size();
|
||||
S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
|
||||
S32 sequence_id = 1;
|
||||
BOOL start_message = TRUE;
|
||||
BOOL initial = TRUE;
|
||||
sendParcelAccessListUpdate(AL_BAN, parcel->mBanList, region, parcel->getLocalID());
|
||||
}
|
||||
|
||||
access_map_const_iterator cit = parcel->mBanList.begin();
|
||||
access_map_const_iterator end = parcel->mBanList.end();
|
||||
while ( (cit != end) || initial )
|
||||
{
|
||||
if (start_message)
|
||||
{
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addU32Fast(_PREHASH_Flags, AL_BAN);
|
||||
msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
|
||||
msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
|
||||
msg->addS32Fast(_PREHASH_Sections, num_sections);
|
||||
start_message = FALSE;
|
||||
|
||||
if (initial && (cit == end))
|
||||
{
|
||||
// pack an empty block if there will be no data
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
|
||||
msg->addS32Fast(_PREHASH_Time, 0 );
|
||||
msg->addU32Fast(_PREHASH_Flags, 0 );
|
||||
}
|
||||
|
||||
initial = FALSE;
|
||||
sequence_id++;
|
||||
|
||||
}
|
||||
|
||||
while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
|
||||
{
|
||||
const LLAccessEntry& entry = (*cit).second;
|
||||
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, entry.mID );
|
||||
msg->addS32Fast(_PREHASH_Time, entry.mTime );
|
||||
msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
|
||||
++cit;
|
||||
}
|
||||
|
||||
start_message = TRUE;
|
||||
msg->sendReliable( region->getHost() );
|
||||
}
|
||||
if(which & AL_ALLOW_EXPERIENCE)
|
||||
{
|
||||
sendParcelAccessListUpdate(AL_ALLOW_EXPERIENCE, parcel->getExperienceKeysByType(EXPERIENCE_KEY_TYPE_ALLOWED), region, parcel->getLocalID());
|
||||
}
|
||||
if(which & AL_BLOCK_EXPERIENCE)
|
||||
{
|
||||
sendParcelAccessListUpdate(AL_BLOCK_EXPERIENCE, parcel->getExperienceKeysByType(EXPERIENCE_KEY_TYPE_BLOCKED), region, parcel->getLocalID());
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 flags, const LLAccessEntry::map& entries, LLViewerRegion* region, S32 parcel_local_id)
|
||||
{
|
||||
S32 count = entries.size();
|
||||
S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
|
||||
S32 sequence_id = 1;
|
||||
BOOL start_message = TRUE;
|
||||
BOOL initial = TRUE;
|
||||
|
||||
LLUUID transactionUUID;
|
||||
transactionUUID.generate();
|
||||
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
LLAccessEntry::map::const_iterator cit = entries.begin();
|
||||
LLAccessEntry::map::const_iterator end = entries.end();
|
||||
while ( (cit != end) || initial )
|
||||
{
|
||||
if (start_message)
|
||||
{
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addU32Fast(_PREHASH_Flags, flags);
|
||||
msg->addS32(_PREHASH_LocalID, parcel_local_id);
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
|
||||
msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
|
||||
msg->addS32Fast(_PREHASH_Sections, num_sections);
|
||||
start_message = FALSE;
|
||||
|
||||
if (initial && (cit == end))
|
||||
{
|
||||
// pack an empty block if there will be no data
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
|
||||
msg->addS32Fast(_PREHASH_Time, 0 );
|
||||
msg->addU32Fast(_PREHASH_Flags, 0 );
|
||||
}
|
||||
|
||||
initial = FALSE;
|
||||
sequence_id++;
|
||||
|
||||
}
|
||||
|
||||
while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
|
||||
{
|
||||
const LLAccessEntry& entry = (*cit).second;
|
||||
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, entry.mID );
|
||||
msg->addS32Fast(_PREHASH_Time, entry.mTime );
|
||||
msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
|
||||
++cit;
|
||||
}
|
||||
|
||||
start_message = TRUE;
|
||||
msg->sendReliable( region->getHost() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLViewerParcelMgr::deedLandToGroup()
|
||||
{
|
||||
std::string group_name;
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ public:
|
|||
|
||||
// Takes an Access List flag, like AL_ACCESS or AL_BAN
|
||||
void sendParcelAccessListUpdate(U32 which);
|
||||
|
||||
|
||||
// Takes an Access List flag, like AL_ACCESS or AL_BAN
|
||||
void sendParcelAccessListRequest(U32 flags);
|
||||
|
||||
|
|
@ -291,6 +291,8 @@ public:
|
|||
static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
|
||||
|
||||
private:
|
||||
static void sendParcelAccessListUpdate(U32 flags, const std::map<LLUUID, class LLAccessEntry>& entries, LLViewerRegion* region, S32 parcel_local_id);
|
||||
static void sendParcelExperienceUpdate( const U32 flags, uuid_vec_t experience_ids, LLViewerRegion* region, S32 parcel_local_id );
|
||||
static bool releaseAlertCB(const LLSD& notification, const LLSD& response);
|
||||
|
||||
// If the user is claiming land and the current selection
|
||||
|
|
|
|||
|
|
@ -2824,8 +2824,21 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
AISCommand::getCapabilityNames(capabilityNames);
|
||||
|
||||
capabilityNames.append("GetDisplayNames");
|
||||
capabilityNames.append("GetExperiences");
|
||||
capabilityNames.append("AgentExperiences");
|
||||
capabilityNames.append("FindExperienceByName");
|
||||
capabilityNames.append("GetExperienceInfo");
|
||||
capabilityNames.append("GetAdminExperiences");
|
||||
capabilityNames.append("GetCreatorExperiences");
|
||||
capabilityNames.append("ExperiencePreferences");
|
||||
capabilityNames.append("GroupExperiences");
|
||||
capabilityNames.append("UpdateExperience");
|
||||
capabilityNames.append("IsExperienceAdmin");
|
||||
capabilityNames.append("IsExperienceContributor");
|
||||
capabilityNames.append("RegionExperiences");
|
||||
capabilityNames.append("GetMesh");
|
||||
capabilityNames.append("GetMesh2");
|
||||
capabilityNames.append("GetMetadata");
|
||||
capabilityNames.append("GetObjectCost");
|
||||
capabilityNames.append("GetObjectPhysicsData");
|
||||
capabilityNames.append("GetTexture");
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "llanimationstates.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llavatarpropertiesprocessor.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llphysicsmotion.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llcallingcard.h" // IDEVO for LLAvatarTracker
|
||||
|
|
@ -2148,7 +2149,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
|
|||
idleUpdateBelowWater(); // wind effect uses this
|
||||
idleUpdateWindEffect();
|
||||
}
|
||||
|
||||
|
||||
idleUpdateNameTag( root_pos_last );
|
||||
idleUpdateRenderCost();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@ const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
|
|||
const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
|
||||
const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
|
||||
|
||||
const U64 GP_EXPERIENCE_ADMIN = 0x1LL << 49; // has admin rights to any experiences owned by this group
|
||||
const U64 GP_EXPERIENCE_CREATOR = 0x1LL << 50; // can sign scripts for experiences owned by this group
|
||||
|
||||
// Group Banning
|
||||
const U64 GP_GROUP_BAN_ACCESS = 0x1LL << 51; // Allows access to ban / un-ban agents from a group.
|
||||
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ with the same filename but different name
|
|||
<texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" />
|
||||
<texture name="ForwardArrow_Press" file_name="icons/ForwardArrow_Press.png" preload="false" />
|
||||
|
||||
<texture name="Generic_Experience" file_name="Blank.png" preload="false" />
|
||||
<texture name="Generic_Group" file_name="icons/Generic_Group.png" preload="false" />
|
||||
<texture name="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" />
|
||||
<texture name="icon_group.tga" file_name="icons/Generic_Group.png" preload="false" />
|
||||
|
|
|
|||
|
|
@ -309,9 +309,6 @@ Nur große Parzellen können in der Suche aufgeführt werden.
|
|||
<panel.string name="push_restrict_region_text">
|
||||
Kein Stoßen (regional)
|
||||
</panel.string>
|
||||
<panel.string name="see_avs_text">
|
||||
Avatare auf anderen Parzellen können
|
||||
</panel.string>
|
||||
<text name="allow_label">
|
||||
Anderen Einwohnern gestatten:
|
||||
</text>
|
||||
|
|
@ -337,22 +334,6 @@ Nur große Parzellen können in der Suche aufgeführt werden.
|
|||
<check_box label="Sicher (kein Schaden)" name="check safe" tool_tip="Falls aktiviert, wird Land auf Option „Sicher“ eingestellt, Kampfschäden sind deaktiviert. Ansonsten sind Kampfschäden aktiviert."/>
|
||||
<check_box label="Kein Stoßen" name="PushRestrictCheck" tool_tip="Verhindert Stoßen durch Skripte. Durch Aktivieren dieser Option verhindern Sie störendes Verhalten auf Ihrem Land."/>
|
||||
<check_box label="Ort in Suche anzeigen (30 L$/Woche)" name="ShowDirectoryCheck" tool_tip="Diese Parzelle in Suchergebnissen anzeigen."/>
|
||||
<combo_box name="land category with adult">
|
||||
<combo_box.item label="Alle Kategorien" name="item0"/>
|
||||
<combo_box.item label="Lindenort" name="item1"/>
|
||||
<combo_box.item label="Adult" name="item2"/>
|
||||
<combo_box.item label="Kunst & Kultur" name="item3"/>
|
||||
<combo_box.item label="Business" name="item4"/>
|
||||
<combo_box.item label="Bildung" name="item5"/>
|
||||
<combo_box.item label="Spielen" name="item6"/>
|
||||
<combo_box.item label="Treffpunkt" name="item7"/>
|
||||
<combo_box.item label="Anfängergerecht" name="item8"/>
|
||||
<combo_box.item label="Parks und Natur" name="item9"/>
|
||||
<combo_box.item label="Wohngebiet" name="item10"/>
|
||||
<combo_box.item label="Shopping" name="item11"/>
|
||||
<combo_box.item label="Vermietung" name="item13"/>
|
||||
<combo_box.item label="Sonstige" name="item12"/>
|
||||
</combo_box>
|
||||
<combo_box name="land category">
|
||||
<combo_box.item label="Alle Kategorien" name="item0"/>
|
||||
<combo_box.item label="Lindenort" name="item1"/>
|
||||
|
|
@ -449,15 +430,9 @@ Nur große Parzellen können in der Suche aufgeführt werden.
|
|||
<panel.string name="access_estate_defined">
|
||||
(Durch Grundbesitz festgelegt)
|
||||
</panel.string>
|
||||
<panel.string name="allow_public_access">
|
||||
Öffentlichen Zugang erlauben ([MATURITY]) (Hinweis: Bei Deaktivierung dieser Option werden Bannlinien generiert)
|
||||
</panel.string>
|
||||
<panel.string name="estate_override">
|
||||
Eine oder mehrere dieser Optionen gelten auf Grundbesitzebene
|
||||
</panel.string>
|
||||
<text name="Limit access to this parcel to:">
|
||||
Zugang zu dieser Parzelle
|
||||
</text>
|
||||
<check_box label="Öffentlichen Zugang gestatten (bei Deaktivierung dieser Option werden Bannlinien generiert)" name="public_access"/>
|
||||
<text name="Only Allow" width="400">
|
||||
Zugang nur Einwohnern gestatten, die:
|
||||
|
|
@ -489,5 +464,6 @@ Nur große Parzellen können in der Suche aufgeführt werden.
|
|||
<button label="Entfernen" label_selected="Entfernen" name="remove_banned"/>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel label="ERLEBNISSE" name="land_experiences_panel"/>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater name="experiencepicker" title="ERLEBNIS AUSWÄHLEN"/>
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater title="EXPERIENCE PROFILE">
|
||||
<floater.string name="empty_slurl">
|
||||
(keines)
|
||||
</floater.string>
|
||||
<floater.string name="maturity_icon_general">
|
||||
"Parcel_PG_Light"
|
||||
</floater.string>
|
||||
<floater.string name="maturity_icon_moderate">
|
||||
"Parcel_M_Light"
|
||||
</floater.string>
|
||||
<floater.string name="maturity_icon_adult">
|
||||
"Parcel_R_Light"
|
||||
</floater.string>
|
||||
<text name="edit_title" value="Erlebnisprofil"/>
|
||||
<tab_container name="tab_container">
|
||||
<panel name="panel_experience_info">
|
||||
<scroll_container name="xp_scroll">
|
||||
<panel name="scrolling_panel">
|
||||
<layout_stack>
|
||||
<layout_panel name="top panel">
|
||||
<button label="Bearbeiten" name="edit_btn"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="maturity panel">
|
||||
<text name="ContentRating">
|
||||
Einstufung:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="location panel">
|
||||
<text name="Location">
|
||||
Standort:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel>
|
||||
<text name="Owner">
|
||||
Eigentümer:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="group_panel">
|
||||
<text name="Group">
|
||||
Gruppe:
|
||||
</text>
|
||||
</layout_panel>
|
||||
<layout_panel name="perm panel">
|
||||
<button label="Zulassen" name="allow_btn"/>
|
||||
<button label="Vergessen" name="forget_btn"/>
|
||||
<button label="Blockieren" name="block_btn"/>
|
||||
<text name="privileged">
|
||||
Dieses Erlebnis ist für alle Einwohner aktiviert.
|
||||
</text>
|
||||
<button label="Missbrauch melden" name="report_btn"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
</scroll_container>
|
||||
</panel>
|
||||
<panel name="edit_panel_experience_info">
|
||||
<scroll_container name="edit_xp_scroll">
|
||||
<panel name="edit_scrolling_panel">
|
||||
<text name="edit_experience_title_label" value="Name:"/>
|
||||
<text name="edit_experience_desc_label" value="Beschreibung:"/>
|
||||
<button label="Gruppe" name="Group_btn"/>
|
||||
<text name="edit_ContentRating">
|
||||
Einstufung:
|
||||
</text>
|
||||
<icons_combo_box label="Moderat" name="edit_ContentRatingText" tool_tip="Bei Erhöhung der Inhaltseinstufung eines Erlebnisses wird die Berechtigung für alle Einwohner zurückgesetzt, die das Erlebnis zugelassen haben.">
|
||||
<icons_combo_box.item label="Adult" name="Adult" value="42"/>
|
||||
<icons_combo_box.item label="Moderat" name="Mature" value="21"/>
|
||||
<icons_combo_box.item label="Allgemein" name="PG" value="13"/>
|
||||
</icons_combo_box>
|
||||
<text name="edit_Location">
|
||||
Standort:
|
||||
</text>
|
||||
<button label="Aktuellen Standort verwenden" name="location_btn"/>
|
||||
<button label="Standort löschen" name="clear_btn"/>
|
||||
<check_box label="Erlebnis aktivieren" name="edit_enable_btn" tool_tip=""/>
|
||||
<check_box label="Aus Suche ausschließen" name="edit_private_btn"/>
|
||||
<text name="changes" value="Es kann mehrere Minuten dauern, bis Erlebnisänderungen in allen Regionen umgesetzt werden."/>
|
||||
<button label="Zurück" name="cancel_btn"/>
|
||||
<button label="Speichern" name="save_btn"/>
|
||||
</panel>
|
||||
</scroll_container>
|
||||
</panel>
|
||||
</tab_container>
|
||||
</floater>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater name="floater_experiences" title="ERLEBNISSE"/>
|
||||
|
|
@ -1,20 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater name="floater_facebook" title="AUF FACEBOOK POSTEN">
|
||||
<panel name="background">
|
||||
<tab_container name="tabs">
|
||||
<panel label="STATUS" name="panel_facebook_status"/>
|
||||
<panel label="FOTO" name="panel_facebook_photo"/>
|
||||
<panel label="EINCHECKEN" name="panel_facebook_place"/>
|
||||
<panel label="FREUNDE" name="panel_facebook_friends"/>
|
||||
<panel label="KONTO" name="panel_facebook_account"/>
|
||||
</tab_container>
|
||||
<panel name="connection_status_panel">
|
||||
<text name="connection_error_text">
|
||||
Fehler
|
||||
</text>
|
||||
<text name="connection_loading_text">
|
||||
Laden...
|
||||
</text>
|
||||
</panel>
|
||||
</panel>
|
||||
<tab_container name="tabs">
|
||||
<panel label="STATUS" name="panel_facebook_status"/>
|
||||
<panel label="FOTO" name="panel_facebook_photo"/>
|
||||
<panel label="EINCHECKEN" name="panel_facebook_place"/>
|
||||
<panel label="FREUNDE" name="panel_facebook_friends"/>
|
||||
</tab_container>
|
||||
<text name="connection_error_text">
|
||||
Fehler
|
||||
</text>
|
||||
<text name="connection_loading_text">
|
||||
Laden...
|
||||
</text>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
<check_box label="Kleidung" name="check_clothing"/>
|
||||
<check_box label="Gesten" name="check_gesture"/>
|
||||
<check_box label="Landmarken" name="check_landmark"/>
|
||||
<check_box label="Netze" name="check_mesh"/>
|
||||
<check_box label="Notizkarten" name="check_notecard"/>
|
||||
<check_box label="Netze" name="check_mesh"/>
|
||||
<check_box label="Objekte" name="check_object"/>
|
||||
<check_box label="Skripts" name="check_script"/>
|
||||
<check_box label="Sounds" name="check_sound"/>
|
||||
|
|
@ -19,6 +19,10 @@
|
|||
<text name="- OR -">
|
||||
- ODER -
|
||||
</text>
|
||||
<radio_group name="date_search_direction">
|
||||
<radio_item label="Neuer als" name="newer"/>
|
||||
<radio_item label="Älter als" name="older"/>
|
||||
</radio_group>
|
||||
<spinner label="Stunden zuvor" label_width="80" name="spin_hours_ago"/>
|
||||
<spinner label="Tage zuvor" name="spin_days_ago"/>
|
||||
<button label="Schließen" label_selected="Schließen" name="Close"/>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
Lag-Anzeige
|
||||
</floater.string>
|
||||
<floater.string name="max_width_px">
|
||||
350
|
||||
360
|
||||
</floater.string>
|
||||
<floater.string name="min_title_msg">
|
||||
Lag
|
||||
|
|
@ -25,10 +25,10 @@
|
|||
Normal, Fenster im Hintergrund
|
||||
</floater.string>
|
||||
<floater.string name="client_frame_time_critical_msg">
|
||||
Client-Frame-Rate unter [CLIENT_FRAME_RATE_CRITICAL]
|
||||
Client-Framerate unter [CLIENT_FRAME_RATE_CRITICAL]
|
||||
</floater.string>
|
||||
<floater.string name="client_frame_time_warning_msg">
|
||||
Client-Frame-Rate zwischen [CLIENT_FRAME_RATE_CRITICAL] und [CLIENT_FRAME_RATE_WARNING]
|
||||
Client-Framerate zwischen [CLIENT_FRAME_RATE_CRITICAL] und [CLIENT_FRAME_RATE_WARNING]
|
||||
</floater.string>
|
||||
<floater.string name="client_frame_time_normal_msg">
|
||||
Normal
|
||||
|
|
@ -55,10 +55,10 @@
|
|||
5
|
||||
</floater.string>
|
||||
<floater.string name="network_packet_loss_critical_msg">
|
||||
Paketverlust der Verbindung übersteigt [NETWORK_PACKET_LOSS_CRITICAL]%
|
||||
Paketverlust der Verbindung übersteigt [NETWORK_PACKET_LOSS_CRITICAL] %
|
||||
</floater.string>
|
||||
<floater.string name="network_packet_loss_warning_msg">
|
||||
Paketverlust der Verbindung liegt bei [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]%
|
||||
Paketverlust der Verbindung liegt bei [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL] %
|
||||
</floater.string>
|
||||
<floater.string name="network_performance_normal_msg">
|
||||
Normal
|
||||
|
|
@ -76,10 +76,10 @@
|
|||
Ping-Zeit der Verbindung liegt bei [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms
|
||||
</floater.string>
|
||||
<floater.string name="network_packet_loss_cause_msg">
|
||||
Möglicherweise schlechte Verbindung oder zu hoher Wert für „Bandbreite“.
|
||||
Möglicherweise schlechte Verbindung oder zu hoher Bandbreitenwert.
|
||||
</floater.string>
|
||||
<floater.string name="network_ping_cause_msg">
|
||||
Möglicherweise schlechte Verbindung oder File-Sharing-Anwendung.
|
||||
Möglicherweise schlechte Verbindung oder Filesharing-Anwendung.
|
||||
</floater.string>
|
||||
<floater.string name="server_text_msg">
|
||||
Server
|
||||
|
|
@ -94,10 +94,10 @@
|
|||
20
|
||||
</floater.string>
|
||||
<floater.string name="server_frame_time_critical_msg">
|
||||
Simulator-Frame-Rate liegt unter [SERVER_FRAME_RATE_CRITICAL]
|
||||
Simulator-Framerate liegt unter [SERVER_FRAME_RATE_CRITICAL]
|
||||
</floater.string>
|
||||
<floater.string name="server_frame_time_warning_msg">
|
||||
Simulator-Frame-Rate liegt zwischen [SERVER_FRAME_RATE_CRITICAL] und [SERVER_FRAME_RATE_WARNING]
|
||||
Simulator-Framerate liegt zwischen [SERVER_FRAME_RATE_CRITICAL] und [SERVER_FRAME_RATE_WARNING]
|
||||
</floater.string>
|
||||
<floater.string name="server_frame_time_normal_msg">
|
||||
Normal
|
||||
|
|
@ -112,13 +112,13 @@
|
|||
Mögliche Ursache: Zu viel Netzwerktraffic
|
||||
</floater.string>
|
||||
<floater.string name="server_agent_cause_msg">
|
||||
Mögliche Ursache: Zu viele Personen in Bewegung in der Region
|
||||
Mögliche Ursache: Zu viele Personen in der Region in Bewegung
|
||||
</floater.string>
|
||||
<floater.string name="server_images_cause_msg">
|
||||
Mögliche Ursache: Zu viele Bildberechnungen
|
||||
</floater.string>
|
||||
<floater.string name="server_generic_cause_msg">
|
||||
Mögliche Ursache: Zu hohe Simulator-Last
|
||||
Mögliche Ursache: Zu hohe Simulatorlast
|
||||
</floater.string>
|
||||
<floater.string name="smaller_label">
|
||||
>>
|
||||
|
|
@ -147,5 +147,5 @@
|
|||
<text name="server_text">
|
||||
Normal
|
||||
</text>
|
||||
<button label=">> " name="minimize" tool_tip="Fenstergröße ändern"/>
|
||||
<button label=">>" name="minimize" tool_tip="Fenstergröße ändern"/>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,24 @@
|
|||
<floater.string name="Title">
|
||||
SKRIPT: [NAME]
|
||||
</floater.string>
|
||||
<floater.string name="experience_enabled">
|
||||
Markierung löschen, um aktuelles Erlebnis zu entfernen
|
||||
</floater.string>
|
||||
<floater.string name="no_experiences">
|
||||
Sie sind zu keinen Erlebnissen berechtigt
|
||||
</floater.string>
|
||||
<floater.string name="add_experiences">
|
||||
Auswählen, um Erlebnis hinzuzufügen
|
||||
</floater.string>
|
||||
<floater.string name="show_experience_profile">
|
||||
Klicken, um Erlebnisprofil aufzurufen
|
||||
</floater.string>
|
||||
<floater.string name="loading">
|
||||
Laden...
|
||||
</floater.string>
|
||||
<button label="Zurücksetzen" label_selected="Zurücksetzen" name="Reset"/>
|
||||
<check_box initial_value="true" label="Läuft" name="running"/>
|
||||
<check_box initial_value="true" label="Mono" name="mono"/>
|
||||
<check_box label="Erlebnis verwenden:" name="enable_xp"/>
|
||||
<button label=">" name="view_profile"/>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@
|
|||
[DESC]:
|
||||
</text>
|
||||
<button label="In Inventar kopieren" label_selected="In Inventar kopieren" name="copy_to_inventory_button" width="120"/>
|
||||
<button label="Kopieren und anziehen" label_selected="Kopieren und anziehen" left_pad="6" name="copy_and_wear_button" width="136"/>
|
||||
<button label="Kopieren und zum Outfit hinzufügen" label_selected="Kopieren und zum Outfit hinzufügen" left_pad="6" name="copy_and_wear_button" width="136"/>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ Objekt:
|
|||
<combo_box.item label="Land > Unbefugte Nutzung > Objekte oder Texturen" name="Land__Encroachment__Objects_textures"/>
|
||||
<combo_box.item label="Land > Unbefugte Nutzung > Partikel" name="Land__Encroachment__Particles"/>
|
||||
<combo_box.item label="Land > Unbefugte Nutzung > Bäume/Pflanzen" name="Land__Encroachment__Trees_plants"/>
|
||||
<combo_box.item label="Wetten/Glücksspiel" name="Wagering_gambling"/>
|
||||
<combo_box.item label="Verstoß gegen die Spielerichtlinie" name="Wagering_gambling"/>
|
||||
<combo_box.item label="Sonstige" name="Other"/>
|
||||
</combo_box>
|
||||
<text name="abuser_name_title">
|
||||
|
|
|
|||
|
|
@ -39,13 +39,7 @@
|
|||
<string name="local_failed_str">
|
||||
Fehler beim Speichern auf dem Computer.
|
||||
</string>
|
||||
<button name="advanced_options_btn" tool_tip="Erweiterte Optionen"/>
|
||||
<text name="image_res_text">
|
||||
[WIDTH]px (Breite) x [HEIGHT]px (Höhe)
|
||||
</text>
|
||||
<text name="file_size_label">
|
||||
[SIZE] KB
|
||||
</text>
|
||||
<button label="AKTUALISIEREN" name="new_snapshot_btn"/>
|
||||
<panel name="advanced_options_panel">
|
||||
<text name="layer_type_label">
|
||||
Aufnehmen:
|
||||
|
|
@ -65,4 +59,10 @@
|
|||
<combo_box.item label="Kein Filter" name="NoFilter"/>
|
||||
</combo_box>
|
||||
</panel>
|
||||
<text name="image_res_text">
|
||||
[WIDTH] px (Breite) x [HEIGHT] px (Höhe)
|
||||
</text>
|
||||
<text name="file_size_label">
|
||||
[SIZE] KB
|
||||
</text>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@
|
|||
<floater.string name="none_descriptor">
|
||||
Nicht gefunden.
|
||||
</floater.string>
|
||||
<floater.string name="URLs">
|
||||
URLs
|
||||
</floater.string>
|
||||
<floater.string name="memory">
|
||||
Speicher (KB)
|
||||
</floater.string>
|
||||
<text name="title_text">
|
||||
Wird geladen...
|
||||
</text>
|
||||
|
|
@ -30,7 +36,7 @@
|
|||
<scroll_list.columns label="Eigentümer" name="owner"/>
|
||||
<scroll_list.columns label="Position" name="location" width="125"/>
|
||||
<scroll_list.columns label="Parzelle" name="parcel"/>
|
||||
<scroll_list.columns label="Uhrzeit" name="time"/>
|
||||
<scroll_list.columns label="Datum" name="time"/>
|
||||
<scroll_list.columns label="URLs" name="URLs"/>
|
||||
<scroll_list.columns label="Speicher (KB)" name="memory"/>
|
||||
</scroll_list>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater name="floater_twitter" title="TWITTER">
|
||||
<panel name="background">
|
||||
<tab_container name="tabs">
|
||||
<panel label="ERSTELLEN" name="panel_twitter_photo"/>
|
||||
<panel label="KONTO" name="panel_twitter_account"/>
|
||||
</tab_container>
|
||||
<panel name="connection_status_panel">
|
||||
<text name="connection_error_text">
|
||||
Fehler
|
||||
</text>
|
||||
<text name="connection_loading_text">
|
||||
Laden...
|
||||
</text>
|
||||
</panel>
|
||||
</panel>
|
||||
<tab_container name="tabs">
|
||||
<panel label="ERSTELLEN" name="panel_twitter_photo"/>
|
||||
<panel label="KONTO" name="panel_twitter_account"/>
|
||||
</tab_container>
|
||||
<text name="connection_error_text">
|
||||
Fehler
|
||||
</text>
|
||||
<text name="connection_loading_text">
|
||||
Laden...
|
||||
</text>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<menu_item_check label="Nach aktuellesten Objekten sortieren" name="sort_by_recent"/>
|
||||
<menu_item_check label="Ordner immer nach Namen sortieren" name="sort_folders_by_name"/>
|
||||
<menu_item_check label="Systemordner nach oben" name="sort_system_folders_to_top"/>
|
||||
<menu_item_call label="Filter anzeigen" name="show_filters"/>
|
||||
<menu_item_call label="Filter anzeigen..." name="show_filters"/>
|
||||
<menu_item_call label="Filter zurücksetzen" name="reset_filters"/>
|
||||
<menu_item_call label="Alle Ordner schließen" name="close_folders"/>
|
||||
<menu_item_call label="Fundbüro ausleeren" name="empty_lostnfound"/>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue