Merge viewer-bear

master
Ansariel 2016-06-24 11:35:43 +02:00
commit 54ad513fcb
27 changed files with 295 additions and 211 deletions

View File

@ -194,7 +194,9 @@ Ansariel Hiller
MAINT-2199
MAINT-6300
MAINT-6397
MAINT-6432
MAINT-6432
MAINT-6513
MAINT-6514
Aralara Rajal
Arare Chantilly
CHUIBUG-191

View File

@ -276,6 +276,8 @@ LLEventPumps::~LLEventPumps()
#pragma warning (push)
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
const std::string LLEventPump::ANONYMOUS = std::string();
LLEventPump::LLEventPump(const std::string& name, bool tweak):
// Register every new instance with LLEventPumps
@ -314,145 +316,162 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
const NameList& after,
const NameList& before)
{
// Check for duplicate name before connecting listener to mSignal
ConnectionMap::const_iterator found = mConnections.find(name);
// In some cases the user might disconnect a connection explicitly -- or
// might use LLEventTrackable to disconnect implicitly. Either way, we can
// end up retaining in mConnections a zombie connection object that's
// already been disconnected. Such a connection object can't be
// reconnected -- nor, in the case of LLEventTrackable, would we want to
// try, since disconnection happens with the destruction of the listener
// object. That means it's safe to overwrite a disconnected connection
// object with the new one we're attempting. The case we want to prevent
// is only when the existing connection object is still connected.
if (found != mConnections.end() && found->second.connected())
float nodePosition = 1.0;
// if the supplied name is empty we are not interested in the ordering mechanism
// and can bypass attempting to find the optimal location to insert the new
// listener. We'll just tack it on to the end.
if (name != ANONYMOUS)
{
throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
"' on " + typeid(*this).name() + " '" + getName() + "'");
}
// Okay, name is unique, try to reconcile its dependencies. Specify a new
// "node" value that we never use for an mSignal placement; we'll fix it
// later.
DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before);
// What if this listener has been added, removed and re-added? In that
// case newNode already has a non-negative value because we never remove a
// listener from mDeps. But keep processing uniformly anyway in case the
// listener was added back with different dependencies. Then mDeps.sort()
// would put it in a different position, and the old newNode placement
// value would be wrong, so we'd have to reassign it anyway. Trust that
// re-adding a listener with the same dependencies is the trivial case for
// mDeps.sort(): it can just replay its cache.
DependencyMap::sorted_range sorted_range;
try
{
// Can we pick an order that works including this new entry?
sorted_range = mDeps.sort();
}
catch (const DependencyMap::Cycle& e)
{
// No: the new node's after/before dependencies have made mDeps
// unsortable. If we leave the new node in mDeps, it will continue
// to screw up all future attempts to sort()! Pull it out.
mDeps.remove(name);
throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
" '" + getName() + "' would cause cycle: " + e.what());
}
// Walk the list to verify that we haven't changed the order.
float previous = 0.0, myprev = 0.0;
DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop
for (DependencyMap::sorted_iterator dmi = sorted_range.begin();
dmi != sorted_range.end(); ++dmi)
{
// Since we've added the new entry with an invalid placement,
// recognize it and skip it.
if (dmi->first == name)
// Check for duplicate name before connecting listener to mSignal
ConnectionMap::const_iterator found = mConnections.find(name);
// In some cases the user might disconnect a connection explicitly -- or
// might use LLEventTrackable to disconnect implicitly. Either way, we can
// end up retaining in mConnections a zombie connection object that's
// already been disconnected. Such a connection object can't be
// reconnected -- nor, in the case of LLEventTrackable, would we want to
// try, since disconnection happens with the destruction of the listener
// object. That means it's safe to overwrite a disconnected connection
// object with the new one we're attempting. The case we want to prevent
// is only when the existing connection object is still connected.
if (found != mConnections.end() && found->second.connected())
{
// Remember the iterator belonging to our new node, and which
// placement value was 'previous' at that point.
mydmi = dmi;
myprev = previous;
continue;
throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
"' on " + typeid(*this).name() + " '" + getName() + "'");
}
// If the new node has rearranged the existing nodes, we'll find
// that their placement values are no longer in increasing order.
if (dmi->second < previous)
// Okay, name is unique, try to reconcile its dependencies. Specify a new
// "node" value that we never use for an mSignal placement; we'll fix it
// later.
DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before);
// What if this listener has been added, removed and re-added? In that
// case newNode already has a non-negative value because we never remove a
// listener from mDeps. But keep processing uniformly anyway in case the
// listener was added back with different dependencies. Then mDeps.sort()
// would put it in a different position, and the old newNode placement
// value would be wrong, so we'd have to reassign it anyway. Trust that
// re-adding a listener with the same dependencies is the trivial case for
// mDeps.sort(): it can just replay its cache.
DependencyMap::sorted_range sorted_range;
try
{
// This is another scenario in which we'd better back out the
// newly-added node from mDeps -- but don't do it yet, we want to
// traverse the existing mDeps to report on it!
// Describe the change to the order of our listeners. Copy
// everything but the newest listener to a vector we can sort to
// obtain the old order.
typedef std::vector< std::pair<float, std::string> > SortNameList;
SortNameList sortnames;
for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end());
cdmi != cdmend; ++cdmi)
{
if (cdmi->first != name)
{
sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first));
}
}
std::sort(sortnames.begin(), sortnames.end());
std::ostringstream out;
out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName()
<< "' would move previous listener '" << dmi->first << "'\nwas: ";
SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end());
if (sni != snend)
{
out << sni->second;
while (++sni != snend)
{
out << ", " << sni->second;
}
}
out << "\nnow: ";
DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end());
if (ddmi != ddmend)
{
out << ddmi->first;
while (++ddmi != ddmend)
{
out << ", " << ddmi->first;
}
}
// NOW remove the offending listener node.
// Can we pick an order that works including this new entry?
sorted_range = mDeps.sort();
}
catch (const DependencyMap::Cycle& e)
{
// No: the new node's after/before dependencies have made mDeps
// unsortable. If we leave the new node in mDeps, it will continue
// to screw up all future attempts to sort()! Pull it out.
mDeps.remove(name);
// Having constructed a description of the order change, inform caller.
throw OrderChange(out.str());
throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
" '" + getName() + "' would cause cycle: " + e.what());
}
// This node becomes the previous one.
previous = dmi->second;
}
// We just got done with a successful mDeps.add(name, ...) call. We'd
// better have found 'name' somewhere in that sorted list!
assert(mydmi != sorted_range.end());
// Four cases:
// 0. name is the only entry: placement 1.0
// 1. name is the first of several entries: placement (next placement)/2
// 2. name is between two other entries: placement (myprev + (next placement))/2
// 3. name is the last entry: placement ceil(myprev) + 1.0
// Since we've cleverly arranged for myprev to be 0.0 if name is the
// first entry, this folds down to two cases. Case 1 is subsumed by
// case 2, and case 0 is subsumed by case 3. So we need only handle
// cases 2 and 3, which means we need only detect whether name is the
// last entry. Increment mydmi to see if there's anything beyond.
if (++mydmi != sorted_range.end())
{
// The new node isn't last. Place it between the previous node and
// the successor.
newNode = (myprev + mydmi->second)/2.f;
}
else
{
// The new node is last. Bump myprev up to the next integer, add
// 1.0 and use that.
newNode = std::ceil(myprev) + 1.f;
// Walk the list to verify that we haven't changed the order.
float previous = 0.0, myprev = 0.0;
DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop
for (DependencyMap::sorted_iterator dmi = sorted_range.begin();
dmi != sorted_range.end(); ++dmi)
{
// Since we've added the new entry with an invalid placement,
// recognize it and skip it.
if (dmi->first == name)
{
// Remember the iterator belonging to our new node, and which
// placement value was 'previous' at that point.
mydmi = dmi;
myprev = previous;
continue;
}
// If the new node has rearranged the existing nodes, we'll find
// that their placement values are no longer in increasing order.
if (dmi->second < previous)
{
// This is another scenario in which we'd better back out the
// newly-added node from mDeps -- but don't do it yet, we want to
// traverse the existing mDeps to report on it!
// Describe the change to the order of our listeners. Copy
// everything but the newest listener to a vector we can sort to
// obtain the old order.
typedef std::vector< std::pair<float, std::string> > SortNameList;
SortNameList sortnames;
for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end());
cdmi != cdmend; ++cdmi)
{
if (cdmi->first != name)
{
sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first));
}
}
std::sort(sortnames.begin(), sortnames.end());
std::ostringstream out;
out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName()
<< "' would move previous listener '" << dmi->first << "'\nwas: ";
SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end());
if (sni != snend)
{
out << sni->second;
while (++sni != snend)
{
out << ", " << sni->second;
}
}
out << "\nnow: ";
DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end());
if (ddmi != ddmend)
{
out << ddmi->first;
while (++ddmi != ddmend)
{
out << ", " << ddmi->first;
}
}
// NOW remove the offending listener node.
mDeps.remove(name);
// Having constructed a description of the order change, inform caller.
throw OrderChange(out.str());
}
// This node becomes the previous one.
previous = dmi->second;
}
// We just got done with a successful mDeps.add(name, ...) call. We'd
// better have found 'name' somewhere in that sorted list!
assert(mydmi != sorted_range.end());
// Four cases:
// 0. name is the only entry: placement 1.0
// 1. name is the first of several entries: placement (next placement)/2
// 2. name is between two other entries: placement (myprev + (next placement))/2
// 3. name is the last entry: placement ceil(myprev) + 1.0
// Since we've cleverly arranged for myprev to be 0.0 if name is the
// first entry, this folds down to two cases. Case 1 is subsumed by
// case 2, and case 0 is subsumed by case 3. So we need only handle
// cases 2 and 3, which means we need only detect whether name is the
// last entry. Increment mydmi to see if there's anything beyond.
if (++mydmi != sorted_range.end())
{
// The new node isn't last. Place it between the previous node and
// the successor.
newNode = (myprev + mydmi->second) / 2.f;
}
else
{
// The new node is last. Bump myprev up to the next integer, add
// 1.0 and use that.
newNode = std::ceil(myprev) + 1.f;
}
nodePosition = newNode;
}
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.
LLBoundListener bound = mSignal->connect(newNode, listener);
mConnections[name] = bound;
LLBoundListener bound = mSignal->connect(nodePosition, listener);
if (name != ANONYMOUS)
{ // note that we are not tracking anonymous listeners here either.
// This means that it is the caller's responsibility to either assign
// to a TempBoundListerer (scoped_connection) or manually disconnect
// when done.
mConnections[name] = bound;
}
return bound;
}

View File

@ -365,6 +365,8 @@ typedef boost::signals2::trackable LLEventTrackable;
class LL_COMMON_API LLEventPump: public LLEventTrackable
{
public:
static const std::string ANONYMOUS; // constant for anonymous listeners.
/**
* Exception thrown by LLEventPump(). You are trying to instantiate an
* LLEventPump (subclass) using the same name as some other instance, and
@ -476,6 +478,12 @@ public:
* instantiate your listener, then passing the same name on each listen()
* call, allows us to optimize away the second and subsequent dependency
* sorts.
*
* If name is set to LLEventPump::ANONYMOUS listen will bypass the entire
* dependency and ordering calculation. In this case, it is critical that
* the result be assigned to a LLTempBoundListener or the listener is
* manually disconnected when no longer needed since there will be no
* way to later find and disconnect this listener manually.
*
* If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
* listener, listen() will inspect the components of that expression. If a

View File

@ -642,7 +642,7 @@ HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request)
mHttpRequest(request)
{
mBoundListener = LLEventPumps::instance().obtain("mainloop").
listen(LLEventPump::inventName(), boost::bind(&HttpRequestPumper::pollRequest, this, _1));
listen(LLEventPump::ANONYMOUS, boost::bind(&HttpRequestPumper::pollRequest, this, _1));
}
HttpRequestPumper::~HttpRequestPumper()

View File

@ -2484,13 +2484,12 @@ void LLFloaterView::restoreAll()
{
// <FS:Ansariel> Possible fix for crash on disconnect
//LLFloater* floaterp = (LLFloater*)*child_it;
//floaterp->setMinimized(FALSE);
LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
// </FS:Ansariel>
if (floaterp)
{
floaterp->setMinimized(FALSE);
}
// </FS:Ansariel>
}
// *FIX: make sure dependents are restored

View File

@ -715,9 +715,10 @@ void LLFolderView::draw()
}
}
if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().contains(mRenamer->getRect()))
if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().overlaps(mRenamer->getRect()))
{
// renamer is not connected to the item we are renaming in any form so manage it manually
// TODO: consider stopping on any scroll action instead of when out of visible area
finishRenamingItem();
}

View File

@ -328,6 +328,15 @@ namespace LLTextValidate
return rv;
}
bool validateASCIINoLeadingSpace(const LLWString &str)
{
if (LLStringOps::isSpace(str[0]))
{
return FALSE;
}
return validateASCII(str);
}
// Used for multiline text stored on the server.
// Example is landmark description in Places SP.
bool validateASCIIWithNewLine(const LLWString &str)

View File

@ -52,6 +52,7 @@ namespace LLTextValidate
bool validateASCIIPrintableNoPipe(const LLWString &str);
bool validateASCIIPrintableNoSpace(const LLWString &str);
bool validateASCII(const LLWString &str);
bool validateASCIINoLeadingSpace(const LLWString &str);
bool validateASCIIWithNewLine(const LLWString &str);
}

View File

@ -4591,11 +4591,17 @@ void LLAgent::handleTeleportFinished()
mIsMaturityRatingChangingDuringTeleport = false;
}
// Init SLM Marketplace connection so we know which UI should be used for the user as a merchant
// Note: Eventually, all merchant will be migrated to the new SLM system and there will be no reason to show the old UI at all.
// Note: Some regions will not support the SLM cap for a while so we need to do that check for each teleport.
// *TODO : Suppress that line from here once the whole grid migrated to SLM and move it to idle_startup() (llstartup.cpp)
check_merchant_status();
if (mRegionp)
{
if (mRegionp->capabilitiesReceived())
{
onCapabilitiesReceivedAfterTeleport();
}
else
{
mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport));
}
}
}
void LLAgent::handleTeleportFailed()
@ -4627,6 +4633,14 @@ void LLAgent::handleTeleportFailed()
}
}
/*static*/
void LLAgent::onCapabilitiesReceivedAfterTeleport()
{
check_merchant_status();
}
void LLAgent::teleportRequest(
const U64& region_handle,
const LLVector3& pos_local,

View File

@ -776,6 +776,8 @@ private:
void handleTeleportFinished();
void handleTeleportFailed();
static void onCapabilitiesReceivedAfterTeleport();
//--------------------------------------------------------------------
// Teleport State
//--------------------------------------------------------------------

View File

@ -79,23 +79,37 @@ using namespace LLAvatarAppearanceDefines;
///////////////////////////////////////////////////////////////////////////////
void set_default_permissions(LLViewerInventoryItem* item)
{
llassert(item);
LLPermissions perm = item->getPermissions();
if (perm.getMaskNextOwner() != LLFloaterPerms::getNextOwnerPerms("Wearables")
|| perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Wearables")
|| perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Wearables"))
{
perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables"));
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables"));
item->setPermissions(perm);
item->updateServer(FALSE);
}
}
// Callback to wear and start editing an item that has just been created.
void wear_and_edit_cb(const LLUUID& inv_item)
{
if (inv_item.isNull()) return;
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (!item) return;
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (!item) return;
LLPermissions perm = item->getPermissions();
perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables"));
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables"));
item->setPermissions(perm);
set_default_permissions(item);
item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
// item was just created, update even if permissions did not changed
gInventory.updateItem(item);
gInventory.notifyObservers();
// Request editing the item after it gets worn.
gAgentWearables.requestEditingWearable(inv_item);
@ -111,13 +125,8 @@ void wear_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables"));
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables"));
item->setPermissions(perm);
set_default_permissions(item);
item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}

View File

@ -2297,10 +2297,7 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
else
{
// This is the inverse of the calculation in updateMaxComplexity
// <FS:Ansariel> Fix math rounding error
//indirect_max_arc = (U32)((log(max_arc) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE) + MIN_INDIRECT_ARC_LIMIT;
indirect_max_arc = (U32)ll_round(((log(F32(max_arc)) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE)) + MIN_INDIRECT_ARC_LIMIT;
// </FS:Ansariel>
}
gSavedSettings.setU32("IndirectMaxComplexity", indirect_max_arc);
}
@ -3126,10 +3123,7 @@ void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* valu
{
// if this is changed, the inverse calculation in setIndirectMaxArc
// must be changed to match
// <FS:Ansariel> Fix math rounding error
//max_arc = (U32)exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT)));
max_arc = (U32)ll_round(exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT))));
// </FS:Ansariel>
}
gSavedSettings.setU32("RenderAvatarMaxComplexity", (U32)max_arc);

View File

@ -259,7 +259,6 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
static std::string badgeOK("badge_ok.j2c");
static std::string badgeNote("badge_note.j2c");
static std::string badgeWarn("badge_warn.j2c");
static std::string badgeError("badge_error.j2c");
std::string badgeName;
switch (badge)
@ -268,7 +267,7 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
case BADGE_OK: badgeName = badgeOK; break;
case BADGE_NOTE: badgeName = badgeNote; break;
case BADGE_WARN: badgeName = badgeWarn; break;
case BADGE_ERROR: badgeName = badgeError; break;
case BADGE_ERROR: badgeName = badgeWarn; break;
}
getChild<LLUICtrl>(id)->setValue(badgeName);

View File

@ -254,7 +254,7 @@ bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
gInventory.collectDescendentsIf (cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
LLInventoryModel::INCLUDE_TRASH,
giveable);
S32 count = cats.size();
bool complete = true;
@ -552,7 +552,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
gInventory.collectDescendentsIf (cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
LLInventoryModel::INCLUDE_TRASH,
giveable);
bool give_successful = true;

View File

@ -628,7 +628,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
// Add the category to the internal representation
LLPointer<LLViewerInventoryCategory> cat =
new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID());
cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
cat->setDescendentCount(0);
LLCategoryUpdate update(cat->getParentUUID(), 1);
accountForUpdate(update);
@ -686,7 +686,7 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(),
result["name"].asString(), gAgent.getID());
cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
cat->setDescendentCount(0);
LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);

View File

@ -774,7 +774,9 @@ void LLMarketplaceData::getMerchantStatusCoro()
std::string url = getSLMConnectURL("/merchant");
if (url.empty())
{
LL_INFOS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL;
LL_WARNS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL;
setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE);
return;
}
LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);

View File

@ -259,7 +259,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor");
mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCII );
mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCIINoLeadingSpace );
}

View File

@ -1074,11 +1074,6 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void)
case LLAssetType::AT_BODYPART:
applyListViewFilter(LVIT_BODYPART);
break;
// <FS:Ansariel> FIRE-19480 / BUG-20032: Selected wearable type in Edit Outfit -> Add more is off by 1
//case LLAssetType::AT_GESTURE:
// applyListViewFilter(LVIT_GESTURES);
// break;
// </FS:Ansariel>
case LLAssetType::AT_CLOTHING:
default:
applyListViewFilter(LVIT_CLOTHING);

View File

@ -80,7 +80,6 @@ public:
{
LVIT_ALL = 0,
LVIT_CLOTHING,
//LVIT_GESTURES, // <FS:Ansariel> FIRE-19480 / BUG-20032: Selected wearable type in Edit Outfit -> Add more is off by 1
LVIT_BODYPART,
LVIT_ATTACHMENT,
LVIT_SHAPE,

View File

@ -204,7 +204,10 @@ void LLPathfindingLinksetList::parseLinksetListData(const LLSD& pLinksetListData
{
const std::string& uuid(linksetDataIter->first);
const LLSD& linksetData = linksetDataIter->second;
LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData));
objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr));
if(linksetData.size() != 0)
{
LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData));
objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr));
}
}
}

View File

@ -79,8 +79,9 @@ void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible)
default:
case BADGE_OK: child->setValue(std::string("badge_ok.j2c")); break;
case BADGE_NOTE: child->setValue(std::string("badge_note.j2c")); break;
case BADGE_WARN: child->setValue(std::string("badge_warn.j2c")); break;
case BADGE_ERROR: child->setValue(std::string("badge_error.j2c")); break;
case BADGE_WARN:
case BADGE_ERROR:
child->setValue(std::string("badge_warn.j2c")); break;
}
}
}

View File

@ -1050,6 +1050,22 @@ void activate_gesture_cb(const LLUUID& inv_item)
LLGestureMgr::instance().activateGesture(inv_item);
}
void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type)
{
llassert(item);
LLPermissions perm = item->getPermissions();
if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type)
|| perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type))
{
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type));
item->setPermissions(perm);
item->updateServer(FALSE);
}
}
void create_script_cb(const LLUUID& inv_item)
{
if (!inv_item.isNull())
@ -1057,13 +1073,9 @@ void create_script_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts"));
set_default_permissions(item, "Scripts");
item->setPermissions(perm);
item->updateServer(FALSE);
// item was just created, update even if permissions did not changed
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@ -1079,13 +1091,8 @@ void create_gesture_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures"));
set_default_permissions(item, "Gestures");
item->setPermissions(perm);
item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
@ -1104,13 +1111,8 @@ void create_notecard_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards"));
set_default_permissions(item, "Notecards");
item->setPermissions(perm);
item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}

View File

@ -467,7 +467,7 @@ void set_merchant_SLM_menu()
gToolBarView->enableCommand(command->id(), true);
}
void check_merchant_status()
void check_merchant_status(bool force)
{
// <FS:Ansariel> Don't show merchant outbox or SL Marketplace stuff outside SL
if (!LLGridManager::getInstance()->isInSecondLife())
@ -479,9 +479,11 @@ void check_merchant_status()
if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth"))
{
// Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
if (force)
{
// Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
}
// Hide SLM related menu item
gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);

View File

@ -89,7 +89,7 @@ BOOL enable_god_full(void* user_data);
BOOL enable_god_liaison(void* user_data);
BOOL enable_god_basic(void* user_data);
void set_underclothes_menu_options();
void check_merchant_status();
void check_merchant_status(bool force = false);
void exchange_callingcard(const LLUUID& dest_id);

View File

@ -1474,10 +1474,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
setChanged(MOVED | SILHOUETTE);
}
else if (mText.notNull())
else
{
mText->markDead();
mText = NULL;
if (mText.notNull())
{
mText->markDead();
mText = NULL;
}
mHudText.clear();
}
std::string media_url;
@ -1858,10 +1862,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
setChanged(TEXTURE);
}
else if(mText.notNull())
else
{
mText->markDead();
mText = NULL;
if (mText.notNull())
{
mText->markDead();
mText = NULL;
}
mHudText.clear();
}
std::string media_url;
@ -5085,8 +5093,20 @@ void LLViewerObject::initHudText()
void LLViewerObject::restoreHudText()
{
if(mText)
if (mHudText.empty())
{
if (mText)
{
mText->markDead();
mText = NULL;
}
}
else
{
if (!mText)
{
initHudText();
}
mText->setColor(mHudTextColor);
mText->setString(mHudText);
}

View File

@ -322,7 +322,7 @@ public:
mBoundListener =
LLEventPumps::instance().
obtain("mainloop").
listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1));
listen(LLEventPump::ANONYMOUS, boost::bind(&Poller::poll, this, _1));
LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL;
}

View File

@ -924,6 +924,9 @@ with the same filename but different name
<texture name="default_land_picture.j2c" />
<texture name="default_profile_picture.j2c" />
<texture name="locked_image.j2c" />
<texture name="badge_note.j2c" />
<texture name="badge_warn.j2c" />
<texture name="badge_ok.j2c" />
<texture name="materials_ui_x_24.png" />
<texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" />