Merge branch 'release/2025.04' into geenz/gltf-mesh-import
commit
bb76eae4b8
|
|
@ -13,7 +13,7 @@ elseif (WINDOWS)
|
|||
foreach(hive HKEY_CURRENT_USER HKEY_LOCAL_MACHINE)
|
||||
# prefer more recent Python versions to older ones, if multiple versions
|
||||
# are installed
|
||||
foreach(pyver 3.12 3.11 3.10 3.9 3.8 3.7)
|
||||
foreach(pyver 3.13 3.12 3.11 3.10 3.9 3.8 3.7)
|
||||
list(APPEND regpaths "[${hive}\\SOFTWARE\\Python\\PythonCore\\${pyver}\\InstallPath]")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
|
|
|||
|
|
@ -506,6 +506,7 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
|
|||
rv = apr_socket_recv(apr_socket, datain, &maxinlen);
|
||||
if (rv != APR_SUCCESS)
|
||||
{
|
||||
// if rv == 70060 it's WSAETIMEDOUT
|
||||
char buf[MAX_STRING];
|
||||
LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
|
||||
ll_apr_warn_status(rv);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,14 @@ void LLChatMentionHelper::showHelper(LLUICtrl* host_ctrl, S32 local_x, S32 local
|
|||
LLRect rect = av_picker_floater->getRect();
|
||||
rect.setLeftTopAndSize(floater_x, floater_y + rect.getHeight(), rect.getWidth(), rect.getHeight());
|
||||
av_picker_floater->setRect(rect);
|
||||
av_picker_floater->openFloater(LLSD().with("av_name", av_name));
|
||||
if (av_picker_floater->isShown())
|
||||
{
|
||||
av_picker_floater->onOpen(LLSD().with("av_name", av_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
av_picker_floater->openFloater(LLSD().with("av_name", av_name));
|
||||
}
|
||||
}
|
||||
|
||||
void LLChatMentionHelper::hideHelper(const LLUICtrl* ctrl)
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ protected:
|
|||
virtual bool isHighlightActive();
|
||||
virtual bool isFadeItem();
|
||||
virtual bool isFlashing() { return false; }
|
||||
virtual void setFlashState(bool) { }
|
||||
virtual void setFlashState(bool, bool) { }
|
||||
|
||||
static LLFontGL* getLabelFontForStyle(U8 style);
|
||||
const LLFontGL* getLabelFont();
|
||||
|
|
|
|||
|
|
@ -630,6 +630,11 @@ LLUUID LLUrlEntryAgent::getID(const std::string &string) const
|
|||
return LLUUID(getIDStringFromUrl(string));
|
||||
}
|
||||
|
||||
bool LLUrlEntryAgent::isAgentID(const std::string& url) const
|
||||
{
|
||||
return sAgentID == getID(url);
|
||||
}
|
||||
|
||||
std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
|
||||
{
|
||||
// return a tooltip corresponding to the URL type instead of the generic one
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public:
|
|||
virtual bool getSkipProfileIcon(const std::string& string) const { return false; }
|
||||
|
||||
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
|
||||
virtual bool isAgentID(const std::string& url) const { return false; }
|
||||
|
||||
bool isLinkDisabled() const;
|
||||
|
||||
|
|
@ -232,6 +233,8 @@ public:
|
|||
/*virtual*/ LLStyle::Params getStyle(const std::string &url) const;
|
||||
/*virtual*/ LLUUID getID(const std::string &string) const;
|
||||
|
||||
bool isAgentID(const std::string& url) const;
|
||||
|
||||
LLStyle::EUnderlineLink getUnderline(const std::string& string) const;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -327,3 +327,30 @@ void LLUrlRegistry::setKeybindingHandler(LLKeyBindingToStringHandler* handler)
|
|||
LLUrlEntryKeybinding *entry = (LLUrlEntryKeybinding*)mUrlEntryKeybinding;
|
||||
entry->setHandler(handler);
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::containsAgentMention(const std::string& text)
|
||||
{
|
||||
// avoid costly regexes if there is clearly no URL in the text
|
||||
if (!stringHasUrl(text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
boost::sregex_iterator it(text.begin(), text.end(), mUrlEntryAgentMention->getPattern());
|
||||
boost::sregex_iterator end;
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (mUrlEntryAgentMention->isAgentID(it->str()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (boost::regex_error&)
|
||||
{
|
||||
LL_INFOS() << "Regex error for: " << text << LL_ENDL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ public:
|
|||
// Set handler for url registry to be capable of parsing and populating keybindings
|
||||
void setKeybindingHandler(LLKeyBindingToStringHandler* handler);
|
||||
|
||||
bool containsAgentMention(const std::string& text);
|
||||
|
||||
private:
|
||||
std::vector<LLUrlEntryBase *> mUrlEntry;
|
||||
LLUrlEntryBase* mUrlEntryTrusted;
|
||||
|
|
|
|||
|
|
@ -430,9 +430,7 @@ void ll_set_device_module_capture_device(rtc::scoped_refptr<webrtc::AudioDeviceM
|
|||
// has it at 0
|
||||
device_module->SetRecordingDevice(device + 1);
|
||||
#endif
|
||||
device_module->SetStereoRecording(false);
|
||||
device_module->InitMicrophone();
|
||||
device_module->InitRecording();
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
|
||||
|
|
@ -473,6 +471,8 @@ void LLWebRTCImpl::setCaptureDevice(const std::string &id)
|
|||
ll_set_device_module_capture_device(mPeerDeviceModule, recordingDevice);
|
||||
if (recording)
|
||||
{
|
||||
mPeerDeviceModule->SetStereoRecording(false);
|
||||
mPeerDeviceModule->InitRecording();
|
||||
mPeerDeviceModule->StartRecording();
|
||||
}
|
||||
});
|
||||
|
|
@ -494,9 +494,7 @@ void ll_set_device_module_render_device(rtc::scoped_refptr<webrtc::AudioDeviceMo
|
|||
#else
|
||||
device_module->SetPlayoutDevice(device + 1);
|
||||
#endif
|
||||
device_module->SetStereoPlayout(true);
|
||||
device_module->InitSpeaker();
|
||||
device_module->InitPlayout();
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setRenderDevice(const std::string &id)
|
||||
|
|
@ -540,6 +538,8 @@ void LLWebRTCImpl::setRenderDevice(const std::string &id)
|
|||
ll_set_device_module_render_device(mPeerDeviceModule, playoutDevice);
|
||||
if (playing)
|
||||
{
|
||||
mPeerDeviceModule->SetStereoPlayout(true);
|
||||
mPeerDeviceModule->InitPlayout();
|
||||
mPeerDeviceModule->StartPlayout();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6361,6 +6361,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PlaySoundChatMention</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Plays a sound when got mentioned in a chat</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PluginAttachDebuggerToPlugins</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -7830,7 +7841,7 @@
|
|||
<key>RenderMinFreeMainMemoryThreshold</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Minimum of available physical memory in MB before textures get scaled down</string>
|
||||
<string>If available free physical memory is below this value textures get agresively scaled down</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -12395,6 +12406,28 @@
|
|||
<key>Value</key>
|
||||
<string>2ca849ba-2885-4bc3-90ef-d4987a5b983a</string>
|
||||
</map>
|
||||
<key>UISndChatMention</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sound file for chat mention(uuid for sound asset)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>03e77cb5-592c-5b33-d271-2e46497c3fb3</string>
|
||||
</map>
|
||||
<key>UISndChatPing</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sound file for chat ping(uuid for sound asset)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>7dd36df6-2624-5438-f988-fdf8588a0ad9</string>
|
||||
</map>
|
||||
<key>UISndClick</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -325,7 +325,8 @@ void LLAvatarListItem::setShowProfileBtn(bool show)
|
|||
|
||||
void LLAvatarListItem::showSpeakingIndicator(bool visible)
|
||||
{
|
||||
if (mSpeakingIndicator)
|
||||
// used only to hide indicator to not contradict with SpeakingIndicatorManager functionality
|
||||
if (mSpeakingIndicator && !visible)
|
||||
{
|
||||
mSpeakingIndicator->setIsActiveChannel(visible);
|
||||
mSpeakingIndicator->setShowParticipantsSpeaking(visible);
|
||||
|
|
|
|||
|
|
@ -86,7 +86,8 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes
|
|||
mHasArrow(true),
|
||||
mIsInActiveVoiceChannel(false),
|
||||
mFlashStateOn(false),
|
||||
mFlashStarted(false)
|
||||
mFlashStarted(false),
|
||||
mIsAltFlashColor(false)
|
||||
{
|
||||
mFlashTimer = new LLFlashTimer();
|
||||
mAreChildrenInited = true; // inventory only
|
||||
|
|
@ -157,7 +158,7 @@ void LLConversationViewSession::destroyView()
|
|||
LLFolderViewFolder::destroyView();
|
||||
}
|
||||
|
||||
void LLConversationViewSession::setFlashState(bool flash_state)
|
||||
void LLConversationViewSession::setFlashState(bool flash_state, bool alternate_color)
|
||||
{
|
||||
if (flash_state && !mFlashStateOn)
|
||||
{
|
||||
|
|
@ -170,6 +171,7 @@ void LLConversationViewSession::setFlashState(bool flash_state)
|
|||
|
||||
mFlashStateOn = flash_state;
|
||||
mFlashStarted = false;
|
||||
mIsAltFlashColor = mFlashStateOn && (alternate_color || mIsAltFlashColor);
|
||||
mFlashTimer->stopFlashing();
|
||||
}
|
||||
|
||||
|
|
@ -288,7 +290,8 @@ void LLConversationViewSession::draw()
|
|||
startFlashing();
|
||||
|
||||
// draw highlight for selected items
|
||||
drawHighlight(show_context, true, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
static LLUIColor alt_color = LLUIColorTable::instance().getColor("MentionFlashBgColor", DEFAULT_WHITE);
|
||||
drawHighlight(show_context, true, sHighlightBgColor, mIsAltFlashColor ? alt_color : sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
|
||||
// Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap.
|
||||
bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen();
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public:
|
|||
|
||||
virtual void refresh();
|
||||
|
||||
/*virtual*/ void setFlashState(bool flash_state);
|
||||
/*virtual*/ void setFlashState(bool flash_state, bool alternate_color = false);
|
||||
void setHighlightState(bool hihglight_state);
|
||||
|
||||
LLFloater* getSessionFloater();
|
||||
|
|
@ -111,6 +111,7 @@ private:
|
|||
LLFlashTimer* mFlashTimer;
|
||||
bool mFlashStateOn;
|
||||
bool mFlashStarted;
|
||||
bool mIsAltFlashColor;
|
||||
|
||||
bool mCollapsedMode;
|
||||
bool mHasArrow;
|
||||
|
|
|
|||
|
|
@ -2302,14 +2302,14 @@ bool LLFloaterIMContainer::isConversationLoggingAllowed()
|
|||
return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes)
|
||||
void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes, bool alternate_color)
|
||||
{
|
||||
//Finds the conversation line item to flash using the session_id
|
||||
LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id));
|
||||
|
||||
if (widget)
|
||||
{
|
||||
widget->setFlashState(is_flashes);
|
||||
widget->setFlashState(is_flashes, alternate_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ public:
|
|||
void reSelectConversation();
|
||||
void updateSpeakBtnState();
|
||||
static bool isConversationLoggingAllowed();
|
||||
void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes);
|
||||
void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes, bool alternate_color = false);
|
||||
void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted);
|
||||
bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget);
|
||||
boost::signals2::connection mMicroChangedSignal;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
#include "llviewerregion.h"
|
||||
#include "llcorehttputil.h"
|
||||
#include "lluiusage.h"
|
||||
#include "llurlregistry.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -197,6 +198,9 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
|
||||
bool store_dnd_message = false; // flag storage of a dnd message
|
||||
bool is_session_focused = session_floater->isTornOff() && session_floater->hasFocus();
|
||||
bool contains_mention = LLUrlRegistry::getInstance()->containsAgentMention(msg["message"].asString());
|
||||
static LLCachedControl<bool> play_snd_mention_pref(gSavedSettings, "PlaySoundChatMention", false);
|
||||
bool play_snd_mention = contains_mention && play_snd_mention_pref && (msg["source_type"].asInteger() != CHAT_SOURCE_OBJECT);
|
||||
if (!LLFloater::isVisible(im_box) || im_box->isMinimized())
|
||||
{
|
||||
conversations_floater_status = CLOSED;
|
||||
|
|
@ -230,7 +234,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
else
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM")))
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM")) && !play_snd_mention)
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
|
|
@ -241,7 +245,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
if (LLAvatarTracker::instance().isBuddy(participant_id))
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM")))
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM")) && !play_snd_mention)
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
|
|
@ -249,7 +253,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
else
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM")))
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM")) && !play_snd_mention)
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
|
|
@ -258,7 +262,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
else if (session->isAdHocSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM")))
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM")) && !play_snd_mention)
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
|
|
@ -266,11 +270,18 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
else if(session->isGroupSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM")))
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM")) && !play_snd_mention)
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
if (play_snd_mention)
|
||||
{
|
||||
if (!gAgent.isDoNotDisturb())
|
||||
{
|
||||
make_ui_sound("UISndChatMention");
|
||||
}
|
||||
}
|
||||
|
||||
// actions:
|
||||
|
||||
|
|
@ -323,7 +334,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
if ("openconversations" == user_preferences
|
||||
|| ON_TOP == conversations_floater_status
|
||||
|| ("toast" == user_preferences && ON_TOP != conversations_floater_status)
|
||||
|| ("flash" == user_preferences && (CLOSED == conversations_floater_status
|
||||
|| (("flash" == user_preferences || contains_mention) && (CLOSED == conversations_floater_status
|
||||
|| NOT_ON_TOP == conversations_floater_status))
|
||||
|| is_dnd_msg)
|
||||
{
|
||||
|
|
@ -343,7 +354,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)
|
|||
}
|
||||
else
|
||||
{
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
im_box->flashConversationItemWidget(session_id, true, contains_mention);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3249,7 +3260,11 @@ void LLIMMgr::addMessage(
|
|||
//Play sound for new conversations
|
||||
if (!skip_message && !gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation")))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
static LLCachedControl<bool> play_snd_mention_pref(gSavedSettings, "PlaySoundChatMention", false);
|
||||
if (!play_snd_mention_pref || !LLUrlRegistry::getInstance()->containsAgentMention(msg))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -3269,7 +3284,7 @@ void LLIMMgr::addMessage(
|
|||
{
|
||||
LLFloaterReg::showInstance("im_container");
|
||||
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->
|
||||
flashConversationItemWidget(new_session_id, true);
|
||||
flashConversationItemWidget(new_session_id, true, LLUrlRegistry::getInstance()->containsAgentMention(msg));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2664,6 +2664,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
//
|
||||
|
||||
bool is_movable = true;
|
||||
bool create_outfit = false;
|
||||
|
||||
if (is_movable && (marketplacelistings_id == cat_id))
|
||||
{
|
||||
|
|
@ -2708,7 +2709,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
tooltip_msg = LLTrans::getString("TooltipOutfitNotInInventory");
|
||||
is_movable = false;
|
||||
}
|
||||
else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
|
||||
else if (can_move_to_my_outfits_as_outfit(model, inv_cat, max_items_to_wear))
|
||||
{
|
||||
is_movable = true;
|
||||
create_outfit = true;
|
||||
}
|
||||
else if (can_move_to_my_outfits_as_subfolder(model, inv_cat))
|
||||
{
|
||||
is_movable = true;
|
||||
}
|
||||
|
|
@ -2742,7 +2748,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
|
||||
else if (can_move_to_my_outfits_as_outfit(model, inv_cat, max_items_to_wear))
|
||||
{
|
||||
is_movable = true;
|
||||
create_outfit = true;
|
||||
}
|
||||
else if (can_move_to_my_outfits_as_subfolder(model, inv_cat))
|
||||
{
|
||||
is_movable = true;
|
||||
}
|
||||
|
|
@ -2943,7 +2954,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
if (mUUID == my_outifts_id)
|
||||
{
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT)
|
||||
if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT || !create_outfit)
|
||||
{
|
||||
LLInvFVBridge::changeCategoryParent(
|
||||
model,
|
||||
|
|
@ -2967,15 +2978,19 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
{
|
||||
case MY_OUTFITS_NO:
|
||||
// Moning from outside outfits into outfits
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER && create_outfit)
|
||||
{
|
||||
// turn it into outfit
|
||||
dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb);
|
||||
dropToMyOutfitsSubfolder(inv_cat, mUUID, cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// or link it?
|
||||
dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb);
|
||||
LLInvFVBridge::changeCategoryParent(
|
||||
model,
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
mUUID,
|
||||
move_is_into_trash);
|
||||
if (cb) cb->fire(inv_cat->getUUID());
|
||||
}
|
||||
break;
|
||||
case MY_OUTFITS_SUBFOLDER:
|
||||
|
|
@ -4094,7 +4109,6 @@ void LLFolderBridge::perform_pasteFromClipboard()
|
|||
LLInventoryObject *obj = model->getObject(item_id);
|
||||
if (obj)
|
||||
{
|
||||
|
||||
if (move_is_into_lost_and_found)
|
||||
{
|
||||
if (LLAssetType::AT_CATEGORY == obj->getType())
|
||||
|
|
@ -4104,41 +4118,57 @@ void LLFolderBridge::perform_pasteFromClipboard()
|
|||
}
|
||||
if (move_is_into_outfit)
|
||||
{
|
||||
if (!move_is_into_my_outfits && item && can_move_to_outfit(item, move_is_into_current_outfit))
|
||||
bool handled = false;
|
||||
if (mUUID != my_outifts_id
|
||||
&& dest_folder->getPreferredType() == LLFolderType::FT_OUTFIT
|
||||
&& item
|
||||
&& can_move_to_outfit(item, move_is_into_current_outfit))
|
||||
{
|
||||
// todo: this is going to create dupplicate folders?
|
||||
dropToOutfit(item, move_is_into_current_outfit, cb);
|
||||
handled = true;
|
||||
}
|
||||
else if (move_is_into_my_outfits && LLAssetType::AT_CATEGORY == obj->getType())
|
||||
{
|
||||
LLInventoryCategory* cat = model->getCategory(item_id);
|
||||
LLViewerInventoryCategory* cat = model->getCategory(item_id);
|
||||
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
|
||||
if (cat && can_move_to_my_outfits(model, cat, max_items_to_wear))
|
||||
if (cat && can_move_to_my_outfits_as_outfit(model, cat, max_items_to_wear))
|
||||
{
|
||||
if (mUUID == my_outifts_id)
|
||||
{
|
||||
dropToMyOutfits(cat, cb);
|
||||
handled = true;
|
||||
}
|
||||
else if (move_is_into_my_outfits)
|
||||
else
|
||||
{
|
||||
EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
if (res == MY_OUTFITS_SUBFOLDER)
|
||||
EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
{
|
||||
// turn it into outfit
|
||||
dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_OUTFIT, cb);
|
||||
dropToMyOutfitsSubfolder(cat, mUUID, cb);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!handled && cat && can_move_to_my_outfits_as_subfolder(model, cat))
|
||||
{
|
||||
EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER || mUUID == my_outifts_id)
|
||||
{
|
||||
if (LLClipboard::instance().isCutMode())
|
||||
{
|
||||
changeCategoryParent(model, cat, parent_id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_NONE, cb);
|
||||
copy_inventory_category(model, cat, parent_id);
|
||||
}
|
||||
if (cb) cb->fire(item_id);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("MyOutfitsPasteFailed");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
LLNotificationsUtil::add("MyOutfitsPasteFailed");
|
||||
}
|
||||
|
|
@ -4181,7 +4211,7 @@ void LLFolderBridge::perform_pasteFromClipboard()
|
|||
// move_inventory_item() is not enough, as we have to update inventory locally too
|
||||
if (LLAssetType::AT_CATEGORY == obj->getType())
|
||||
{
|
||||
LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
|
||||
LLViewerInventoryCategory* vicat = model->getCategory(item_id);
|
||||
llassert(vicat);
|
||||
if (vicat)
|
||||
{
|
||||
|
|
@ -5478,12 +5508,11 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI
|
|||
inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb)
|
||||
void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel);
|
||||
getInventoryModel()->createNewCategory(dest_id,
|
||||
preferred_type,
|
||||
LLFolderType::FT_OUTFIT,
|
||||
inv_cat->getName(),
|
||||
func,
|
||||
inv_cat->getThumbnailUUID());
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ protected:
|
|||
void dropToFavorites(LLInventoryItem* inv_item, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToOutfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Messy hacks for handling folder options
|
||||
|
|
|
|||
|
|
@ -438,7 +438,13 @@ void copy_inventory_category(LLInventoryModel* model,
|
|||
{
|
||||
copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items);
|
||||
};
|
||||
gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID());
|
||||
LLFolderType::EType type = LLFolderType::FT_NONE;
|
||||
if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
// at the moment only permitting copy of outfits and normal folders
|
||||
type = LLFolderType::FT_OUTFIT;
|
||||
}
|
||||
gInventory.createNewCategory(parent_id, type, cat->getName(), func, cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void copy_inventory_category(LLInventoryModel* model,
|
||||
|
|
@ -460,6 +466,25 @@ void copy_inventory_category(LLInventoryModel* model,
|
|||
gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void copy_inventory_category(LLInventoryModel* model,
|
||||
LLViewerInventoryCategory* cat,
|
||||
const LLUUID& parent_id,
|
||||
const LLUUID& root_copy_id,
|
||||
bool move_no_copy_items,
|
||||
LLPointer<LLInventoryCallback> callback)
|
||||
{
|
||||
// Create the initial folder
|
||||
inventory_func_type func = [model, cat, root_copy_id, move_no_copy_items, callback](const LLUUID& new_id)
|
||||
{
|
||||
copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items);
|
||||
if (callback)
|
||||
{
|
||||
callback.get()->fire(new_id);
|
||||
}
|
||||
};
|
||||
gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void copy_cb(const LLUUID& dest_folder, const LLUUID& root_id)
|
||||
{
|
||||
// Decrement the count in root_id since that one item won't be copied over
|
||||
|
|
@ -2314,7 +2339,7 @@ bool can_move_to_landmarks(LLInventoryItem* inv_item)
|
|||
}
|
||||
|
||||
// Returns true if folder's content can be moved to Current Outfit or any outfit folder.
|
||||
bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit)
|
||||
bool can_move_to_my_outfits_as_outfit(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit)
|
||||
{
|
||||
LLInventoryModel::cat_array_t *cats;
|
||||
LLInventoryModel::item_array_t *items;
|
||||
|
|
@ -2353,6 +2378,51 @@ bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_ca
|
|||
return true;
|
||||
}
|
||||
|
||||
bool can_move_to_my_outfits_as_subfolder(LLInventoryModel* model, LLInventoryCategory* inv_cat, S32 depth)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
model->getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
|
||||
|
||||
if (items->size() > 0)
|
||||
{
|
||||
// subfolders don't allow items
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inv_cat->getPreferredType() != LLFolderType::FT_NONE)
|
||||
{
|
||||
// only normal folders can become subfodlers
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr size_t MAX_CONTENT = 255;
|
||||
if (cats->size() > MAX_CONTENT)
|
||||
{
|
||||
// don't allow massive folders
|
||||
return false;
|
||||
}
|
||||
|
||||
for (LLPointer<LLViewerInventoryCategory>& cat : *cats)
|
||||
{
|
||||
// outfits are valid to move, check non-outfit folders
|
||||
if (cat->getPreferredType() != LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
if (depth == 3)
|
||||
{
|
||||
// don't allow massive folders
|
||||
return false;
|
||||
}
|
||||
if (!can_move_to_my_outfits_as_subfolder(model, cat, depth + 1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string get_localized_folder_name(LLUUID cat_uuid)
|
||||
{
|
||||
std::string localized_root_name;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
|
|||
|
||||
void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null, bool move_no_copy_items = false);
|
||||
void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id, bool move_no_copy_items, inventory_func_type callback);
|
||||
void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id, bool move_no_copy_items, LLPointer<LLInventoryCallback> callback);
|
||||
|
||||
void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items);
|
||||
|
||||
|
|
@ -112,7 +113,8 @@ std::string get_category_path(LLUUID cat_id);
|
|||
|
||||
bool can_move_to_outfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit);
|
||||
bool can_move_to_landmarks(LLInventoryItem* inv_item);
|
||||
bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit);
|
||||
bool can_move_to_my_outfits_as_outfit(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit);
|
||||
bool can_move_to_my_outfits_as_subfolder(LLInventoryModel* model, LLInventoryCategory* inv_cat, S32 depth = 0);
|
||||
std::string get_localized_folder_name(LLUUID cat_uuid);
|
||||
void new_folder_window(const LLUUID& folder_id);
|
||||
void ungroup_folder_items(const LLUUID& folder_id);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value imm
|
|||
bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, bool drop, std::string& tooltip_msg, bool is_link);
|
||||
bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm);
|
||||
void dropToMyOutfits(LLInventoryCategory* inv_cat);
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type);
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id);
|
||||
|
||||
class LLGalleryPanel: public LLPanel
|
||||
{
|
||||
|
|
@ -3714,6 +3714,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
//
|
||||
|
||||
bool is_movable = true;
|
||||
bool create_outfit = false;
|
||||
|
||||
if (is_movable && (marketplacelistings_id == cat_id))
|
||||
{
|
||||
|
|
@ -3759,7 +3760,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
tooltip_msg = LLTrans::getString("TooltipOutfitNotInInventory");
|
||||
is_movable = false;
|
||||
}
|
||||
else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
|
||||
else if (can_move_to_my_outfits_as_outfit(model, inv_cat, max_items_to_wear))
|
||||
{
|
||||
is_movable = true;
|
||||
create_outfit = true;
|
||||
}
|
||||
else if (can_move_to_my_outfits_as_subfolder(model, inv_cat))
|
||||
{
|
||||
is_movable = true;
|
||||
}
|
||||
|
|
@ -3793,7 +3799,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
|
||||
else if (can_move_to_my_outfits_as_outfit(model, inv_cat, max_items_to_wear))
|
||||
{
|
||||
is_movable = true;
|
||||
create_outfit = true;
|
||||
}
|
||||
else if (can_move_to_my_outfits_as_subfolder(model, inv_cat))
|
||||
{
|
||||
is_movable = true;
|
||||
}
|
||||
|
|
@ -3928,7 +3939,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
if (dest_id == my_outifts_id)
|
||||
{
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT)
|
||||
if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT || !create_outfit)
|
||||
{
|
||||
gInventory.changeCategoryParent(
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
|
|
@ -3950,14 +3961,17 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
{
|
||||
case MY_OUTFITS_NO:
|
||||
// Moning from outside outfits into outfits
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER && create_outfit)
|
||||
{
|
||||
// turn it into outfit
|
||||
dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT);
|
||||
dropToMyOutfitsSubfolder(inv_cat, dest_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE);
|
||||
gInventory.changeCategoryParent(
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
dest_id,
|
||||
move_is_into_trash);
|
||||
}
|
||||
break;
|
||||
case MY_OUTFITS_SUBFOLDER:
|
||||
|
|
@ -4136,10 +4150,10 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat)
|
|||
gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id, LLFolderType::EType preferred_type)
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id)
|
||||
{
|
||||
// Note: creation will take time, so passing folder id to callback is slightly unreliable,
|
||||
// but so is collecting and passing descendants' ids
|
||||
inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1);
|
||||
gInventory.createNewCategory(dest_id, preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
|
||||
gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5976,13 +5976,7 @@ bool LLMeshRepository::meshUploadEnabled()
|
|||
bool LLMeshRepository::meshRezEnabled()
|
||||
{
|
||||
static LLCachedControl<bool> mesh_enabled(gSavedSettings, "MeshEnabled");
|
||||
LLViewerRegion *region = gAgent.getRegion();
|
||||
if(mesh_enabled &&
|
||||
region)
|
||||
{
|
||||
return region->meshRezEnabled();
|
||||
}
|
||||
return false;
|
||||
return mesh_enabled;
|
||||
}
|
||||
|
||||
// Threading: main thread only
|
||||
|
|
|
|||
|
|
@ -2498,6 +2498,8 @@ void LLModelPreview::updateStatusMessages()
|
|||
S32 phys_tris = 0;
|
||||
S32 phys_hulls = 0;
|
||||
S32 phys_points = 0;
|
||||
S32 which_mode = 0;
|
||||
S32 file_mode = 1;
|
||||
|
||||
//get the triangle count for the whole scene
|
||||
for (LLModelLoader::scene::iterator iter = mScene[LLModel::LOD_PHYSICS].begin(), endIter = mScene[LLModel::LOD_PHYSICS].end(); iter != endIter; ++iter)
|
||||
|
|
@ -2619,18 +2621,16 @@ void LLModelPreview::updateStatusMessages()
|
|||
fmp->childEnable("simplify_cancel");
|
||||
fmp->childEnable("decompose_cancel");
|
||||
}
|
||||
|
||||
LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo");
|
||||
if (iface)
|
||||
{
|
||||
which_mode = iface->getFirstSelectedIndex();
|
||||
file_mode = iface->getItemCount() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo");
|
||||
S32 which_mode = 0;
|
||||
S32 file_mode = 1;
|
||||
if (iface)
|
||||
{
|
||||
which_mode = iface->getFirstSelectedIndex();
|
||||
file_mode = iface->getItemCount() - 1;
|
||||
}
|
||||
|
||||
if (which_mode == file_mode)
|
||||
{
|
||||
mFMP->childEnable("physics_file");
|
||||
|
|
|
|||
|
|
@ -793,6 +793,17 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
|
|||
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
|
||||
if (!cat) return;
|
||||
|
||||
if (!isOutfitFolder(cat))
|
||||
{
|
||||
// Assume a subfolder that contains or will contain outfits, track it
|
||||
const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
mOutfitsObserver->addCategory(cat_id, [this, outfits]()
|
||||
{
|
||||
observerCallback(outfits);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name = cat->getName();
|
||||
LLOutfitGalleryItem* item = buildGalleryItem(name, cat_id);
|
||||
mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item));
|
||||
|
|
|
|||
|
|
@ -142,6 +142,17 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
|
|||
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
|
||||
if (!cat) return;
|
||||
|
||||
if (!isOutfitFolder(cat))
|
||||
{
|
||||
// Assume a subfolder that contains or will contain outfits, track it
|
||||
const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
mCategoriesObserver->addCategory(cat_id, [this, outfits]()
|
||||
{
|
||||
observerCallback(outfits);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name = cat->getName();
|
||||
|
||||
outfit_accordion_tab_params tab_params(get_accordion_tab_params());
|
||||
|
|
@ -819,49 +830,38 @@ void LLOutfitListBase::observerCallback(const LLUUID& category_id)
|
|||
refreshList(category_id);
|
||||
}
|
||||
|
||||
class LLIsOutfitListFolder : public LLInventoryCollectFunctor
|
||||
bool LLOutfitListBase::isOutfitFolder(LLViewerInventoryCategory* cat) const
|
||||
{
|
||||
public:
|
||||
LLIsOutfitListFolder()
|
||||
if (!cat)
|
||||
{
|
||||
mOutfitsId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
}
|
||||
virtual ~LLIsOutfitListFolder() {}
|
||||
|
||||
bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override
|
||||
{
|
||||
if (cat)
|
||||
{
|
||||
if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (cat->getPreferredType() == LLFolderType::FT_NONE
|
||||
&& cat->getParentUUID() == mOutfitsId)
|
||||
{
|
||||
LLViewerInventoryCategory* inv_cat = dynamic_cast<LLViewerInventoryCategory*>(cat);
|
||||
if (inv_cat && inv_cat->getDescendentCount() > 3)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
|
||||
if (cats->empty() // protection against outfits inside
|
||||
&& items->size() > 3) // eyes, skin, hair and shape are required
|
||||
{
|
||||
// For now assume this to be an old style outfit, not a subfolder
|
||||
// but ideally no such 'outfits' should be left in My Outfits
|
||||
// Todo: stop counting FT_NONE as outfits,
|
||||
// convert obvious outfits into FT_OUTFIT
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected:
|
||||
LLUUID mOutfitsId;
|
||||
};
|
||||
if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// assumes that folder is somewhere inside MyOutfits
|
||||
if (cat->getPreferredType() == LLFolderType::FT_NONE)
|
||||
{
|
||||
LLViewerInventoryCategory* inv_cat = dynamic_cast<LLViewerInventoryCategory*>(cat);
|
||||
if (inv_cat && inv_cat->getDescendentCount() > 3)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
|
||||
if (cats->empty() // protection against outfits inside
|
||||
&& items->size() > 3) // arbitrary, if doesn't have at least base parts, not an outfit
|
||||
{
|
||||
// For now assume this to be an old style outfit, not a subfolder
|
||||
// but ideally no such 'outfits' should be left in My Outfits
|
||||
// Todo: stop counting FT_NONE as outfits,
|
||||
// convert obvious outfits into FT_OUTFIT
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLOutfitListBase::refreshList(const LLUUID& category_id)
|
||||
{
|
||||
|
|
@ -872,13 +872,13 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
|
|||
LLInventoryModel::item_array_t item_array;
|
||||
|
||||
// Collect all sub-categories of a given category.
|
||||
LLIsOutfitListFolder is_outfit;
|
||||
LLIsType is_category(LLAssetType::AT_CATEGORY);
|
||||
gInventory.collectDescendentsIf(
|
||||
category_id,
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_outfit);
|
||||
is_category);
|
||||
|
||||
// Memorize item names for each UUID
|
||||
std::map<LLUUID, std::string> names;
|
||||
|
|
@ -1396,7 +1396,12 @@ bool LLOutfitAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
{
|
||||
LLSD params;
|
||||
params["inv_type"] = LLInventoryType::IT_CATEGORY;
|
||||
params["thumbnail_id"] = gInventory.getCategory(mFolderID)->getThumbnailUUID();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(mFolderID);
|
||||
if (cat)
|
||||
{
|
||||
params["thumbnail_id"] = cat->getThumbnailUUID();
|
||||
}
|
||||
// else consider returning
|
||||
params["item_id"] = mFolderID;
|
||||
|
||||
LLToolTipMgr::instance().show(LLToolTip::Params()
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ protected:
|
|||
void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
|
||||
virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0;
|
||||
|
||||
bool isOutfitFolder(LLViewerInventoryCategory* cat) const;
|
||||
|
||||
static void onIdle(void* userdata);
|
||||
void onIdleRefreshList();
|
||||
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ void init_audio()
|
|||
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowClose")));
|
||||
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowOpen")));
|
||||
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndRestart")));
|
||||
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndChatMention")));
|
||||
}
|
||||
|
||||
audio_update_volume(true);
|
||||
|
|
|
|||
|
|
@ -73,12 +73,14 @@ LLViewerCamera::LLViewerCamera() : LLCamera()
|
|||
mAverageSpeed = 0.f;
|
||||
mAverageAngularSpeed = 0.f;
|
||||
|
||||
mCameraAngleChangedSignal = gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2));
|
||||
}
|
||||
|
||||
LLViewerCamera::~LLViewerCamera()
|
||||
{
|
||||
mCameraAngleChangedSignal.disconnect();
|
||||
LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl("CameraAngle");
|
||||
if (cntrl_ptr.notNull())
|
||||
{
|
||||
cntrl_ptr->getCommitSignal()->connect([](LLControlVariable* control, const LLSD& value, const LLSD& previous)
|
||||
{
|
||||
LLViewerCamera::getInstance()->setDefaultFOV((F32)value.asReal());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest)
|
||||
|
|
@ -814,8 +816,3 @@ bool LLViewerCamera::isDefaultFOVChanged()
|
|||
return false;
|
||||
}
|
||||
|
||||
void LLViewerCamera::updateCameraAngle(const LLSD& value)
|
||||
{
|
||||
setDefaultFOV((F32)value.asReal());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ class alignas(16) LLViewerCamera : public LLCamera, public LLSimpleton<LLViewerC
|
|||
LL_ALIGN_NEW
|
||||
public:
|
||||
LLViewerCamera();
|
||||
~LLViewerCamera();
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
@ -66,7 +65,6 @@ public:
|
|||
const LLVector3 &point_of_interest);
|
||||
|
||||
static void updateFrustumPlanes(LLCamera& camera, bool ortho = false, bool zflip = false, bool no_hacks = false);
|
||||
void updateCameraAngle(const LLSD& value);
|
||||
void setPerspective(bool for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, bool limit_select_distance, F32 z_near = 0, F32 z_far = 0);
|
||||
|
||||
const LLMatrix4 &getProjection() const;
|
||||
|
|
@ -126,8 +124,6 @@ protected:
|
|||
F32 mZoomFactor;
|
||||
S16 mZoomSubregion;
|
||||
|
||||
boost::signals2::connection mCameraAngleChangedSignal;
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2583,6 +2583,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
|
|||
msg_notify["session_id"] = LLUUID();
|
||||
msg_notify["from_id"] = chat.mFromID;
|
||||
msg_notify["source_type"] = chat.mSourceType;
|
||||
// used to check if there is agent mention in the message
|
||||
msg_notify["message"] = mesg;
|
||||
on_new_message(msg_notify);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3720,12 +3720,6 @@ bool LLViewerRegion::bakesOnMeshEnabled() const
|
|||
mSimulatorFeatures["BakesOnMeshEnabled"].asBoolean());
|
||||
}
|
||||
|
||||
bool LLViewerRegion::meshRezEnabled() const
|
||||
{
|
||||
return (mSimulatorFeatures.has("MeshRezEnabled") &&
|
||||
mSimulatorFeatures["MeshRezEnabled"].asBoolean());
|
||||
}
|
||||
|
||||
bool LLViewerRegion::dynamicPathfindingEnabled() const
|
||||
{
|
||||
return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") &&
|
||||
|
|
|
|||
|
|
@ -333,7 +333,6 @@ public:
|
|||
|
||||
void getInfo(LLSD& info);
|
||||
|
||||
bool meshRezEnabled() const;
|
||||
bool meshUploadEnabled() const;
|
||||
|
||||
bool bakesOnMeshEnabled() const;
|
||||
|
|
|
|||
|
|
@ -1008,5 +1008,8 @@
|
|||
value="0.82 0.91 0.98 0.15" />
|
||||
<color
|
||||
name="ChatSelfMentionHighlight"
|
||||
value="1 1 0 1" />
|
||||
value="1 1 0 0.35" />
|
||||
<color
|
||||
name="MentionFlashBgColor"
|
||||
value="1 1 0 0.5" />
|
||||
</colors>
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@
|
|||
layout="topleft"
|
||||
left="0"
|
||||
name="play_sound"
|
||||
width="100"
|
||||
width="90"
|
||||
top_pad="8"
|
||||
visible="true">
|
||||
Play sound:
|
||||
|
|
@ -419,10 +419,10 @@
|
|||
height="16"
|
||||
label="New conversation"
|
||||
layout="topleft"
|
||||
left_pad="15"
|
||||
left_pad="5"
|
||||
top_pad="-10"
|
||||
name="new_conversation"
|
||||
width="150" />
|
||||
width="130" />
|
||||
<check_box
|
||||
control_name="PlaySoundIncomingVoiceCall"
|
||||
height="16"
|
||||
|
|
@ -430,16 +430,16 @@
|
|||
layout="topleft"
|
||||
top_pad="6"
|
||||
name="incoming_voice_call"
|
||||
width="150" />
|
||||
width="130" />
|
||||
<check_box
|
||||
control_name="PlaySoundTeleportOffer"
|
||||
height="16"
|
||||
label="Teleport offer"
|
||||
layout="topleft"
|
||||
left_pad="35"
|
||||
left_pad="18"
|
||||
top_pad="-38"
|
||||
name="teleport_offer"
|
||||
width="150" />
|
||||
width="130" />
|
||||
<check_box
|
||||
control_name="PlaySoundInventoryOffer"
|
||||
height="16"
|
||||
|
|
@ -447,14 +447,23 @@
|
|||
layout="topleft"
|
||||
top_pad="6"
|
||||
name="inventory_offer"
|
||||
width="150" />
|
||||
width="130" />
|
||||
<check_box
|
||||
control_name="PlaySoundChatMention"
|
||||
height="16"
|
||||
label="Chat mention"
|
||||
layout="topleft"
|
||||
left_pad="7"
|
||||
top_pad="-38"
|
||||
name="chat_mention"
|
||||
width="130" />
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="cost_text_border"
|
||||
top_pad="7"
|
||||
top_pad="29"
|
||||
width="492"/>
|
||||
</panel>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue